Skip to content

Commit ec45a00

Browse files
committed
refactor: consolidate scoring logic into singleton
1 parent 7cdc05f commit ec45a00

File tree

7 files changed

+66
-55
lines changed

7 files changed

+66
-55
lines changed

models/array_model.gd

-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
class_name ArrayModel
2-
extends Reference
32

43
# For all parameterized signals, i <= j
54
signal removed(i)

models/binary_tree_model.gd

-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
class_name BinaryTreeModel
2-
extends Reference
32

43
var left: BinaryTreeModel setget set_left
54
var right: BinaryTreeModel setget set_right

project.godot

+1-6
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,6 @@ _global_script_classes=[ {
6464
"language": "GDScript",
6565
"path": "res://levels/quick_sort.gd"
6666
}, {
67-
"base": "Reference",
68-
"class": "Score",
69-
"language": "GDScript",
70-
"path": "res://scripts/score.gd"
71-
}, {
7267
"base": "ComparisonSort",
7368
"class": "SelectionSort",
7469
"language": "GDScript",
@@ -91,7 +86,6 @@ _global_script_class_icons={
9186
"InsertionSort": "",
9287
"MergeSort": "",
9388
"QuickSort": "",
94-
"Score": "",
9589
"SelectionSort": "",
9690
"ShellSort": ""
9791
}
@@ -107,6 +101,7 @@ config/icon="res://assets/icon.png"
107101

108102
GlobalScene="*res://scripts/scene.gd"
109103
GlobalTheme="*res://scripts/theme.gd"
104+
GlobalScore="*res://scripts/score.gd"
110105

111106
[display]
112107

scripts/levels.gd

+7-9
Original file line numberDiff line numberDiff line change
@@ -49,22 +49,20 @@ func _ready():
4949
func _on_Button_focus_entered(size=_level.array.size):
5050
# Update high scores
5151
var buttons = $LevelsBorder/Levels/LevelsContainer/Buttons
52-
var save = GlobalScene.read_save()
5352
for i in range(LEVELS.size()):
5453
var score = $LevelsBorder/Levels/LevelsContainer/Scores.get_child(i)
5554
var name = buttons.get_child(i).text
56-
if name in save and str(size) in save[name]:
57-
var moves = save[name][str(size)][0]
58-
var time = save[name][str(size)][1]
59-
score.get_child(0).text = "%.3f" % time
60-
score.get_child(1).text = Score.get_tier(moves, time)
61-
score.get_child(1).add_color_override(
62-
"font_color", Score.get_color(moves, time))
63-
else:
55+
var time = GlobalScore.get_time(name, size)
56+
if time == INF:
6457
score.get_child(0).text = ""
6558
score.get_child(1).text = "INF"
6659
score.get_child(1).add_color_override(
6760
"font_color", GlobalTheme.GREEN)
61+
else:
62+
score.get_child(0).text = "%.3f" % time
63+
score.get_child(1).text = GlobalScore.get_tier(name, size)
64+
score.get_child(1).add_color_override(
65+
"font_color", GlobalScore.get_color(name, size))
6866
# Pause a bit to show completely sorted array
6967
if _level.array.is_sorted():
7068
# Prevent race condition caused by keyboard input during pause

scripts/play.gd

+11-18
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,14 @@ var _level = GlobalScene.get_param(
55
"level", preload("res://scripts/levels.gd").LEVELS[0])
66

77
func _ready():
8+
set_process(false)
89
$HUDBorder/HUD/Level.text = _level.new(ArrayModel.new()).NAME
910

1011
func _process(delta):
11-
if _start_time >= 0:
12-
$HUDBorder/HUD/Score.text = "%.3f" % get_score()
12+
$HUDBorder/HUD/Score.text = "%.3f" % get_score()
1313

1414
func _on_Timer_timeout():
15+
set_process(true)
1516
_start_time = OS.get_ticks_msec()
1617
$Display/Label.queue_free() # Delete ready text
1718
var level = _level.new(ArrayModel.new(
@@ -28,8 +29,11 @@ func _input(event):
2829
_on_Button_pressed("levels")
2930

3031
func _on_Level_done(level):
31-
var moves = level.moves
32+
set_process(false)
33+
var name = level.NAME
34+
var size = level.array.size
3235
var score = get_score()
36+
var moves = level.moves
3337
var restart = Button.new()
3438
restart.text = "RESTART LEVEL"
3539
restart.connect("pressed", self, "_on_Button_pressed", ["play"])
@@ -42,11 +46,11 @@ func _on_Level_done(level):
4246
time.text = "%.3f" % score
4347
time.align = Label.ALIGN_RIGHT
4448
time.size_flags_horizontal = Control.SIZE_EXPAND_FILL
45-
_start_time = -1
4649
var tier = Label.new()
47-
tier.text = Score.get_tier(moves, score)
50+
tier.text = GlobalScore.calculate_tier(score, moves)
4851
tier.align = Label.ALIGN_RIGHT
49-
tier.add_color_override("font_color", Score.get_color(moves, score))
52+
tier.add_color_override(
53+
"font_color", GlobalScore.calculate_color(score, moves))
5054
$HUDBorder/HUD/Level.queue_free()
5155
$HUDBorder/HUD/Score.queue_free()
5256
$HUDBorder/HUD.add_child(restart)
@@ -55,18 +59,7 @@ func _on_Level_done(level):
5559
$HUDBorder/HUD.add_child(time)
5660
$HUDBorder/HUD.add_child(tier)
5761
restart.grab_focus()
58-
var save = GlobalScene.read_save()
59-
var name = level.NAME
60-
var size = str(GlobalScene.get_param("size", ArrayModel.DEFAULT_SIZE))
61-
if not name in save:
62-
save[name] = {}
63-
if not size in save[name]:
64-
save[name][size] = [-1, INF]
65-
var mps1 = Score.get_mps_int(moves, score)
66-
var mps2 = Score.get_mps_int(save[name][size][0], save[name][size][1])
67-
if mps1 > mps2 or mps1 == mps2 and score < save[name][size][1]:
68-
save[name][size] = [moves, score]
69-
GlobalScene.write_save(save)
62+
GlobalScore.save_score(name, size, score, moves)
7063

7164
func _on_Button_pressed(scene):
7265
GlobalScene.change_scene("res://scenes/" + scene + ".tscn",

scripts/scene.gd

-12
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,3 @@ func get_param(name, default=null):
1414
if _params != null and _params.get(name) != null:
1515
return _params[name]
1616
return default
17-
18-
func read_save():
19-
var file = File.new()
20-
file.open("user://save.json", File.READ)
21-
return {} if not file.is_open() else parse_json(file.get_as_text())
22-
file.close()
23-
24-
func write_save(save):
25-
var file = File.new()
26-
file.open("user://save.json", File.WRITE)
27-
file.store_line(to_json(save))
28-
file.close()

scripts/score.gd

+47-8
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
"""
22
Common helper library for scoring functions.
33
"""
4-
class_name Score
5-
extends Reference
4+
5+
extends Node
66

77
const TIERS = ["F", "D", "C", "B", "A", "S"]
88
const COLORS = [
@@ -14,11 +14,50 @@ const COLORS = [
1414
Color("e040fb"),
1515
]
1616

17-
static func get_tier(moves, seconds):
18-
return TIERS[get_mps_int(moves, seconds)]
17+
var _save: Dictionary
18+
19+
func _init():
20+
var file = File.new()
21+
file.open("user://save.json", File.READ)
22+
_save = {} if not file.is_open() else parse_json(file.get_as_text())
23+
file.close()
24+
25+
func get_time(name, size):
26+
if name in _save and str(size) in _save[name]:
27+
return _save[name][str(size)][0]
28+
return INF
29+
30+
func get_tier(name, size):
31+
if name in _save and str(size) in _save[name]:
32+
return _save[name][str(size)][1]
33+
return ""
34+
35+
func get_color(name, size):
36+
var tier = get_tier(name, size)
37+
return Color.black if tier.empty() else COLORS[TIERS.find(tier)]
38+
39+
func calculate_tier(time, moves):
40+
return TIERS[min(int(moves / time), TIERS.size() - 1)]
41+
42+
func calculate_color(time, moves):
43+
return COLORS[TIERS.find(calculate_tier(time, moves))]
1944

20-
static func get_mps_int(moves, seconds):
21-
return int(min(moves / seconds, TIERS.size() - 1))
45+
func save_score(name, size, time, moves):
46+
if not name in _save:
47+
_save[name] = {}
48+
if not str(size) in _save[name]:
49+
_save[name][str(size)] = [INF, ""]
50+
var prev_time = get_time(name, size)
51+
var prev_tier = get_tier(name, size)
52+
var tier = calculate_tier(time, moves)
53+
var tier_index = TIERS.find(tier)
54+
if (prev_tier.empty() or tier_index > TIERS.find(prev_tier)
55+
or tier_index == TIERS.find(prev_tier) and time < prev_time):
56+
_save[name][str(size)] = [time, tier]
57+
_save()
2258

23-
static func get_color(moves, seconds):
24-
return COLORS[min(moves / seconds, COLORS.size() - 1)]
59+
func _save():
60+
var file = File.new()
61+
file.open("user://save.json", File.WRITE)
62+
file.store_line(to_json(_save))
63+
file.close()

0 commit comments

Comments
 (0)