Skip to content

Commit

Permalink
Round floats before encoding
Browse files Browse the repository at this point in the history
  • Loading branch information
Gatsik committed May 23, 2022
1 parent 67ce446 commit 2a356ce
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 32 deletions.
4 changes: 2 additions & 2 deletions server/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,8 @@ def __init__(self):
self.QUEUE_POP_DESIRED_MATCHES = 2.5
# How many previous queue sizes to consider
self.QUEUE_POP_TIME_MOVING_AVG_SIZE = 5
# The number of decimal places to use for float serialization
self.JSON_FLOAT_DIGITS_PRECISION = 2
# The maximum number of decimal places to use for float serialization
self.JSON_FLOAT_MAX_DIGITS = 2

self._defaults = {
key: value for key, value in vars(self).items() if key.isupper()
Expand Down
35 changes: 10 additions & 25 deletions server/protocol/protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,32 +10,17 @@


class CustomJSONEncoder(json.JSONEncoder):
# taken from https://stackoverflow.com/a/60243503
# taken from https://stackoverflow.com/a/53798633
def encode(self, o):
if isinstance(o, dict):
dict_content = []
for key, value in o.items():
# do not use precision for float dict keys
if (isinstance(key, int) or isinstance(key, float)):
new_key = f'"{key}"'.lower()
elif key is None:
new_key = '"null"'
elif isinstance(key, str):
new_key = self.encode(key)
else:
raise TypeError(
'Keys must be str, int, float, bool or None, '
f'not {key.__class__.__name__}',
)
new_value = self.encode(value)
dict_content.append(f"{new_key}:{new_value}")
return "{" + ",".join(dict_content) + "}"
elif isinstance(o, (list, tuple)) and not isinstance(o, str):
return "[" + ",".join(map(self.encode, o)) + "]"
elif isinstance(o, float):
return f"{o:.{config.JSON_FLOAT_DIGITS_PRECISION}f}"
else:
return super().encode(o)
def round_floats(o):
if isinstance(o, float):
return round(o, config.JSON_FLOAT_MAX_DIGITS)
if isinstance(o, dict):
return {k: round_floats(v) for k, v in o.items()}
if isinstance(o, (list, tuple)):
return [round_floats(x) for x in o]
return o
return super().encode(round_floats(o))


json_encoder = CustomJSONEncoder(separators=(",", ":"))
Expand Down
4 changes: 2 additions & 2 deletions tests/integration_tests/test_game.py
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ async def test_game_ended_rates_game(lobby_server):
async def test_game_ended_broadcasts_rating_update(
lobby_server, channel, mocker,
):
mocker.patch("server.config.JSON_FLOAT_DIGITS_PRECISION", 4)
mocker.patch("server.config.JSON_FLOAT_MAX_DIGITS", 4)
mq_proto_all = await connect_mq_consumer(
lobby_server,
channel,
Expand Down Expand Up @@ -620,7 +620,7 @@ async def test_ladder_game_draw_bug(lobby_server, database, mocker):
their own ACU in order to kill the enemy ACU and be awarded a victory
instead of a draw.
"""
mocker.patch("server.config.JSON_FLOAT_DIGITS_PRECISION", 13)
mocker.patch("server.config.JSON_FLOAT_MAX_DIGITS", 13)
player1_id, proto1, player2_id, proto2 = await queue_players_for_matchmaking(lobby_server)

msg1, msg2 = await asyncio.gather(*[
Expand Down
6 changes: 3 additions & 3 deletions tests/unit_tests/test_protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,9 +262,9 @@ async def test_read_when_disconnected(protocol):


def test_json_encoder_float_serialization():
assert json_encoder.encode(123.0) == '123.00'
assert json_encoder.encode(123.0) == '123.0'
assert json_encoder.encode(0.99) == '0.99'
assert json_encoder.encode(0.999) == '1.00'
assert json_encoder.encode(0.999) == '1.0'


def test_json_encoder_encodes_server_messages():
Expand Down Expand Up @@ -305,7 +305,7 @@ def test_json_encoder_encodes_server_messages():

for queue in expected_matchmaker_info_dict["queues"]:
queue["queue_pop_time_delta"] = round(
queue["queue_pop_time_delta"], config.JSON_FLOAT_DIGITS_PRECISION,
queue["queue_pop_time_delta"], config.JSON_FLOAT_MAX_DIGITS,
)

assert new_encode(matchmaker_info_dict) == (
Expand Down

0 comments on commit 2a356ce

Please sign in to comment.