Skip to content

Commit

Permalink
Merge pull request #25 from yokenzan/yokenzan/fix-kakkotsuki-mark
Browse files Browse the repository at this point in the history
fix(format): カッコ付き数字の置換処理で常に⑴を返してしまう不具合を修正
  • Loading branch information
yokenzan authored Jan 31, 2023
2 parents b627149 + fa3a4c8 commit bb3fe8c
Show file tree
Hide file tree
Showing 9 changed files with 173 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def load(csv_paths)
pattern: Treatment::Comment::Pattern.find_by_code(
values[Treatment::Comment::Columns::C_パターン]
),
name: convert_kakkotsuki_mark(
name: replace_kakkotsuki_mark(
convert_unit(convert_unit(values[Treatment::Comment::Columns::C_コメント文_漢字名称]))
),
name_kana: convert_katakana(values[Treatment::Comment::Columns::C_コメント文_カナ名称]),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def load(csv_paths)
code = Treatment::Iyakuhin::Code.of(values[Treatment::Iyakuhin::Columns::C_コード])
hash[code.value] = Treatment::Iyakuhin.new(
code: code,
name: convert_kakkotsuki_mark(
name: replace_kakkotsuki_mark(
convert_unit(values[Treatment::Iyakuhin::Columns::C_医薬品名・規格名_漢字名称])
),
name_kana: convert_katakana(values[Treatment::Iyakuhin::Columns::C_医薬品名・規格名_カナ名称]),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def foreach(csv_paths)
def_delegators Receiptisan::Util::Formatter,
:convert_katakana,
:convert_unit,
:convert_kakkotsuki_mark
:replace_kakkotsuki_mark
end
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def load(version, csv_paths)
code = Treatment::ShinryouKoui::Code.of(values[columns::C_コード])
hash[code.value] = Treatment::ShinryouKoui.new(
code: code,
name: convert_kakkotsuki_mark(
name: replace_kakkotsuki_mark(
convert_unit(values[columns::C_省略名称_漢字名称])
),
name_kana: convert_katakana(values[columns::C_省略名称_カナ名称]),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def load(csv_paths)
code = Treatment::TokuteiKizai::Code.of(values[Treatment::TokuteiKizai::Columns::C_コード])
hash[code.value] = Treatment::TokuteiKizai.new(
code: code,
name: convert_kakkotsuki_mark(
name: replace_kakkotsuki_mark(
convert_unit(values[Treatment::TokuteiKizai::Columns::C_特定器材名・規格名_漢字名称])
),
name_kana: convert_katakana(values[Treatment::TokuteiKizai::Columns::C_特定器材名・規格名_カナ名称]),
Expand Down
22 changes: 7 additions & 15 deletions lib/receiptisan/util/formatter.rb
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
# frozen_string_literal: true

require_relative 'formatter/kakkotsuki_formatter'

module Receiptisan
module Util
module Formatter
MARU_ICHI_CODEPOINT = 0x2460 # ①~⑳のコードポイント
MARU_ICHI_CODEPOINT_21 = 0x3251 # ㉑以降のコードポイント
MARU_ICHI_CODEPOINT_36 = 0x32b1 # ㊱以降のコードポイント
KAKKO_ICHI_CODEPOINT = 0x2474 # ⑴のコードポイント
HANKAKU_CHARS = '−() A-Za-z0-9.'
ZENKAKU_CHARS = '―() A-Za-z0-9.'

# カンマ区切り表記にする
# @param integer [Integer, nil] nilの場合は空文字列を返します
# @return [String]
def to_currency(integer)
return '' if integer.nil?
def to_currency(value)
return '' unless value.respond_to?(:to_i)

integer.to_s.gsub(/(\d)(?=(\d{3})+(?!\d))/, '\1,')
value.to_i.to_s.gsub(/(\d)(?=(\d{3})+(?!\d))/, '\1,')
end

# マル付数字の文字を生成する
Expand All @@ -39,14 +40,9 @@ def to_marutsuki_mark(zero_based_index)
codepoint.chr('UTF-8')
end

# カッコ付数字の文字を生成する
# @param zero_based_index [Integer]
# @return [String]
def to_kakkotsuki_mark(zero_based_index)
# 用意されている文字はカッコ20まで
raise ArgumentError, "given index is out of range (0~19): '#{zero_based_index}'" if zero_based_index >= 20

(KAKKO_ICHI_CODEPOINT + zero_based_index).chr('UTF-8')
def replace_kakkotsuki_mark(string)
KakkotsukiFormatter.format(string)
end

# @param value [String, Symbol, Integer, nil] nilの場合は空文字列を返します
Expand All @@ -73,10 +69,6 @@ def convert_katakana(hankaku)
NKF.nkf('-wWX', hankaku)
end

def convert_kakkotsuki_mark(string)
string.gsub(/(([0-9]{1,2}))/) { | m | to_kakkotsuki_mark(to_hankaku(m).to_i) }
end

def convert_unit(string)
string
.gsub('mLV', '㎖V')
Expand Down
45 changes: 45 additions & 0 deletions lib/receiptisan/util/formatter/kakkotsuki_formatter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# frozen_string_literal: true

module Receiptisan
module Util
module Formatter
module KakkotsukiFormatter
Formatter = ::Receiptisan::Util::Formatter

KAKKO_ICHI_CODEPOINT = 0x2474 # ⑴のコードポイント
TARGET_RANGE = 1..20

# カッコ付数字の文字が含まれていたら置換する
# @return [String]
def format(string)
string.gsub(/(([1-9][0-9]*))/) do
matched_number = ::Regexp.last_match(1)
number = Formatter.to_hankaku(matched_number).to_i
convertable?(number) ? convert(number - 1) : matched_number
end
end

# カッコ付数字の文字を生成する
# @param zero_based_index [Integer]
# @return [String]
def convert(zero_based_index)
# 用意されている文字はカッコ20まで
unless convertable?(zero_based_index + 1)
min = TARGET_RANGE.begin - 1
max = TARGET_RANGE.end - 1

raise ArgumentError, "given index is out of range (#{min}~#{max}): '#{zero_based_index}'"
end

(KAKKO_ICHI_CODEPOINT + zero_based_index).chr('UTF-8')
end

def convertable?(number)
number.between?(TARGET_RANGE.begin, TARGET_RANGE.end)
end

module_function :format, :convert, :convertable?
end
end
end
end
67 changes: 67 additions & 0 deletions spec/lib/receiptisan/util/formatter/kakkotsuki_formatter_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# frozen_string_literal: true

require 'receiptisan'

RSpec.describe Receiptisan::Util::Formatter::KakkotsukiFormatter do
describe '#convert' do
context '0を渡したとき' do
specify '⑴を返す' do
expect(described_class.convert(0)).to eq '⑴'
end
end

context '1を渡したとき' do
specify '⑵を返す' do
expect(described_class.convert(1)).to eq '⑵'
end
end

context '3を渡したとき' do
specify '⑶を返す' do
expect(described_class.convert(2)).to eq '⑶'
end
end

context '19を渡したとき' do
specify '⒇を返す' do
expect(described_class.convert(19)).to eq '⒇'
end
end

context '20を渡したとき' do
specify '(21)は表示不可能なので範囲外である旨例外を投げる' do
expect { described_class.convert(20) }.to raise_error(ArgumentError, "given index is out of range (0~19): '20'")
end
end
end

describe '#format' do
context 'カッコ数字を含む文字列を渡したとき' do
context '「生化学的検査(1)判断料」を渡したとき' do
specify '「生化学的検査⑴判断料」を返す' do
expect(described_class.format('生化学的検査(1)判断料')).to eq '生化学的検査⑴判断料'
end
end

context '「生化学的検査(2)判断料」を渡したとき' do
specify '「生化学的検査⑵判断料」を返す' do
expect(described_class.format('生化学的検査(2)判断料')).to eq '生化学的検査⑵判断料'
end
end
end

context('カッコ数字を含まない文字列を渡したとき') do
context '「処方箋料(リフィル以外・その他)」を渡したとき' do
specify '何も変更せず「処方箋料(リフィル以外・その他)」を返す' do
expect(described_class.format('処方箋料(リフィル以外・その他)')).to eq '処方箋料(リフィル以外・その他)'
end
end

context '「一般名処方加算2(処方箋料)」を渡したとき' do
specify '何も変更せず「一般名処方加算2(処方箋料)」を返す' do
expect(described_class.format('一般名処方加算2(処方箋料)')).to eq '一般名処方加算2(処方箋料)'
end
end
end
end
end
49 changes: 49 additions & 0 deletions spec/lib/receiptisan/util/formatter_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# frozen_string_literal: true

require 'receiptisan'

RSpec.describe Receiptisan::Util::Formatter do
# TODO: Integer以外のパターン

describe '#to_currency' do
context '正の整数' do
context '4桁のとき' do
specify '千の位と百の位の間にカンマを付した文字列を返すこと' do
expect(described_class.to_currency(1234)).to eq '1,234'
end
end

context '6桁のとき' do
specify '千の位と百の位の間にカンマを付した文字列を返すこと' do
expect(described_class.to_currency(123_456)).to eq '123,456'
end
end

context '7桁のとき' do
specify '百万の位と十万の位、千の位と百の位の間にそれぞれカンマを付した文字列を返すこと' do
expect(described_class.to_currency(1_234_567)).to eq '1,234,567'
end
end

context '3桁のとき' do
specify 'カンマを付さず3桁の数値を文字列として返すこと' do
expect(described_class.to_currency(123)).to eq '123'
end
end
end

context '負の整数' do
context '4桁のとき' do
specify 'マイナス符号つきの、千の位と百の位の間にカンマを付した文字列を返すこと' do
expect(described_class.to_currency(-1234)).to eq '-1,234'
end
end

context '3桁のとき' do
specify 'カンマを付さず3桁の数値を文字列として返すこと' do
expect(described_class.to_currency(-123)).to eq '-123'
end
end
end
end
end

0 comments on commit bb3fe8c

Please sign in to comment.