Skip to content

Commit c972c57

Browse files
committed
refactor: Split SegmentOptimizer#_compute_costs into three methods
1 parent 91995b7 commit c972c57

File tree

1 file changed

+50
-23
lines changed

1 file changed

+50
-23
lines changed

src/rmqrcode/segments.py

Lines changed: 50 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -107,36 +107,63 @@ def _compute_costs(self, data):
107107
if not encoders[new_mode].is_valid_characters(data[n]):
108108
continue
109109

110-
encoder_class = encoders[new_mode]
111-
character_count_indicator_length = self.qr_version["character_count_indicator_length"][
112-
encoder_class
113-
]
114110
if new_mode == mode:
115-
# Keep the mode
116-
if encoder_class == encoder.NumericEncoder:
117-
new_length = (unfilled_length + 1) % 3
118-
cost = 4 if unfilled_length == 0 else 3
119-
elif encoder_class == encoder.AlphanumericEncoder:
120-
new_length = (unfilled_length + 1) % 2
121-
cost = 6 if unfilled_length == 0 else 5
122-
elif encoder_class == encoder.ByteEncoder:
123-
new_length = 0
124-
cost = 8 * len(data[n].encode("utf-8"))
125-
elif encoder_class == encoder.KanjiEncoder:
126-
new_length = 0
127-
cost = 13
111+
cost, new_length = self._compute_new_state_without_mode_changing(data[n], new_mode, unfilled_length)
128112
else:
129-
# Change the mode
130-
if encoder_class in [encoder.NumericEncoder, encoder.AlphanumericEncoder]:
131-
new_length = 1
132-
elif encoder_class in [encoder.ByteEncoder, encoder.KanjiEncoder]:
133-
new_length = 0
134-
cost = encoders[new_mode].length(data[n], character_count_indicator_length)
113+
cost, new_length = self._compute_new_state_with_mode_changing(data[n], new_mode, unfilled_length)
135114

136115
if self.dp[n][mode][unfilled_length] + cost < self.dp[n + 1][new_mode][new_length]:
137116
self.dp[n + 1][new_mode][new_length] = self.dp[n][mode][unfilled_length] + cost
138117
self.parents[n + 1][new_mode][new_length] = (n, mode, unfilled_length)
139118

119+
def _compute_new_state_without_mode_changing(self, character, new_mode, unfilled_length):
120+
"""Computes the new state without mode changing.
121+
122+
Args:
123+
character (str): The current character. Assume this as one length string.
124+
new_mode (int): The state of the new mode.
125+
unfilled_length (int): The state of the current unfilled_length.
126+
127+
Returns:
128+
tuple: (cost, new_length).
129+
130+
"""
131+
encoder_class = encoders[new_mode]
132+
if encoder_class == encoder.NumericEncoder:
133+
new_length = (unfilled_length + 1) % 3
134+
cost = 4 if unfilled_length == 0 else 3
135+
elif encoder_class == encoder.AlphanumericEncoder:
136+
new_length = (unfilled_length + 1) % 2
137+
cost = 6 if unfilled_length == 0 else 5
138+
elif encoder_class == encoder.ByteEncoder:
139+
new_length = 0
140+
cost = 8 * len(character.encode("utf-8"))
141+
elif encoder_class == encoder.KanjiEncoder:
142+
new_length = 0
143+
cost = 13
144+
return (cost, new_length)
145+
146+
def _compute_new_state_with_mode_changing(self, character, new_mode, unfilled_length):
147+
"""Computes the new state with mode changing.
148+
149+
Args:
150+
character (str): The current character. Assume this as one length string.
151+
new_mode (int): The state of the new mode.
152+
unfilled_length (int): The state of the current unfilled_length.
153+
154+
Returns:
155+
tuple: (cost, new_length).
156+
157+
"""
158+
encoder_class = encoders[new_mode]
159+
character_count_indicator_length = self.qr_version["character_count_indicator_length"][encoder_class]
160+
if encoder_class in [encoder.NumericEncoder, encoder.AlphanumericEncoder]:
161+
new_length = 1
162+
elif encoder_class in [encoder.ByteEncoder, encoder.KanjiEncoder]:
163+
new_length = 0
164+
cost = encoder_class.length(character, character_count_indicator_length)
165+
return (cost, new_length)
166+
140167
def _find_best(self, data):
141168
"""Find the index which has the minimum costs.
142169

0 commit comments

Comments
 (0)