Skip to content
Snippets Groups Projects
Verified Commit e693876e authored by dos's avatar dos
Browse files

High scores

parent 3a8bc242
Branches
Tags
No related merge requests found
...@@ -24,6 +24,7 @@ class DifficultyView(BaseView): ...@@ -24,6 +24,7 @@ class DifficultyView(BaseView):
if len(self.song.difficulties) > 2: if len(self.song.difficulties) > 2:
self._sc.set_position(1) self._sc.set_position(1)
self._scroll_pos = 0 self._scroll_pos = 0
self.song.readScores()
def draw(self, ctx: Context) -> None: def draw(self, ctx: Context) -> None:
...@@ -96,15 +97,23 @@ class DifficultyView(BaseView): ...@@ -96,15 +97,23 @@ class DifficultyView(BaseView):
ctx.move_to (0, -78) ctx.move_to (0, -78)
ctx.text("DIFFICULTY") ctx.text("DIFFICULTY")
""" if self.song.difficulties:
ctx.font_size = 15 score = self.song.scores[self.song.difficulties[self._sc.target_position()]]
ctx.move_to(0, 78) if not score.empty():
ctx.text("Put songs into")
ctx.move_to(0, 94)
ctx.font_size = 15 ctx.font_size = 15
ctx.gray(0.75) ctx.gray(0.5)
ctx.text("/sd/PetalHero") ctx.text_align = ctx.RIGHT
""" ctx.font = "Material Icons"
ctx.move_to(-7, 86)
ctx.text("\ue885")
ctx.move_to(-7, 102)
ctx.text("\uea0b")
ctx.font = "Camp Font 3"
ctx.text_align = ctx.LEFT
ctx.move_to(-5, 83)
ctx.text(f"{int(score.max_acc.accuracy * 100)}%")
ctx.move_to(-5, 99)
ctx.text(str(score.max_streak.streak))
def think(self, ins: InputState, delta_ms: int) -> None: def think(self, ins: InputState, delta_ms: int) -> None:
super().think(ins, delta_ms) super().think(ins, delta_ms)
......
...@@ -38,6 +38,9 @@ class ScoreView(BaseView): ...@@ -38,6 +38,9 @@ class ScoreView(BaseView):
self.accuracy = len(set(filter(lambda x: x.played and not x.missed, events))) / (len(events) + badnotes) self.accuracy = len(set(filter(lambda x: x.played and not x.missed, events))) / (len(events) + badnotes)
self.stars = int(5.0 * (self.accuracy + 0.05)) self.stars = int(5.0 * (self.accuracy + 0.05))
self.highscore = self.song.recordScore(difficulty, self.accuracy, streak, badnotes)
self.timeout = 5 if self.highscore else 0
def draw(self, ctx: Context) -> None: def draw(self, ctx: Context) -> None:
#utils.background(ctx) #utils.background(ctx)
utils.clear(ctx) utils.clear(ctx)
...@@ -97,10 +100,21 @@ class ScoreView(BaseView): ...@@ -97,10 +100,21 @@ class ScoreView(BaseView):
ctx.text(f"Longest streak: {self.streak}") ctx.text(f"Longest streak: {self.streak}")
ctx.font = "Camp Font 3" ctx.font = "Camp Font 3"
ctx.font_size = 16
ctx.text_align = ctx.CENTER ctx.text_align = ctx.CENTER
ctx.text_baseline = ctx.MIDDLE ctx.text_baseline = ctx.MIDDLE
alpha = min(self.timeout, 0.5) / 0.5
if alpha > 0:
ctx.global_alpha = alpha
utils.fire_gradient(ctx)
ctx.font_size = 18
ctx.move_to(0, 85 - math.sin(self.time * 4) * 2)
ctx.text("New highscore!")
if alpha < 1:
ctx.global_alpha = 1.0 - alpha
ctx.gray(0.5) ctx.gray(0.5)
ctx.font_size = 16
ctx.move_to(0, 84 - math.sin(self.time * 4) * 2) ctx.move_to(0, 84 - math.sin(self.time * 4) * 2)
ctx.text("Press the button...") ctx.text("Press the button...")
...@@ -109,6 +123,9 @@ class ScoreView(BaseView): ...@@ -109,6 +123,9 @@ class ScoreView(BaseView):
media.think(delta_ms) media.think(delta_ms)
utils.blm_timeout(self, delta_ms) utils.blm_timeout(self, delta_ms)
self.time += delta_ms / 1000 self.time += delta_ms / 1000
self.timeout -= delta_ms / 1000
if self.timeout < 0:
self.timeout = 0
if self.time > 1.5 and not self.played: if self.time > 1.5 and not self.played:
self.played = True self.played = True
......
import os import os
import sys import sys
import struct
from .configparser import ConfigParser from .configparser import ConfigParser
...@@ -40,6 +41,41 @@ class MidiInfoReader(MidiOutStream): ...@@ -40,6 +41,41 @@ class MidiInfoReader(MidiOutStream):
if len(self.difficulties) == len(difficulties): if len(self.difficulties) == len(difficulties):
raise MidiInfoReader.Done() raise MidiInfoReader.Done()
class Score():
accuracy = None
streak = None
badnotes = None
def __init__(self, score = None):
if score is not None:
self.accuracy = score.accuracy
self.streak = score.streak
self.badnotes = score.badnotes
def __eq__(self, score):
return self.accuracy == score.accuracy and self.streak == score.streak and self.badnotes == score.badnotes
def empty(self):
return self.accuracy is None or self.streak is None or self.badnotes is None
def __repr__(self):
if self.empty():
return "Score()"
return f"Score(acc: {self.accuracy}, str: {self.streak}, bn: {self.badnotes})"
class ScoreSet():
def __init__(self):
self.max_acc = Score()
self.max_streak = Score()
def empty(self):
return self.max_acc.empty() and self.max_streak.empty()
def __repr__(self):
if self.empty():
return "ScoreSet()"
return f"ScoreSet(max_acc: {str(self.max_acc)}, max_str: {str(self.max_streak)})"
class SongInfo(object): class SongInfo(object):
def __init__(self, dirName): def __init__(self, dirName):
infoFileName = dirName + "/song.ini" infoFileName = dirName + "/song.ini"
...@@ -48,6 +84,7 @@ class SongInfo(object): ...@@ -48,6 +84,7 @@ class SongInfo(object):
self.fileName = infoFileName self.fileName = infoFileName
self.info = ConfigParser() self.info = ConfigParser()
self._difficulties = None self._difficulties = None
self._scores = None
try: try:
self.info.read(infoFileName) self.info.read(infoFileName)
...@@ -143,6 +180,91 @@ class SongInfo(object): ...@@ -143,6 +180,91 @@ class SongInfo(object):
except Exception as e: except Exception as e:
sys.print_exception(e) sys.print_exception(e)
def readScores(self):
self._scores = {}
for diff in difficulties.values():
self._scores[diff] = ScoreSet()
scoreFileName = os.path.join(os.path.dirname(self.fileName), ".score.pet")
if not os.path.exists(scoreFileName):
return self._scores
try:
with open(scoreFileName, "rb") as f:
magic = f.read(7)
assert(magic == b"PHSCORE")
ver = f.read(1)
assert(ver == b"\0")
length = f.read(1)[0]
for i in range(length):
diff = f.read(1)[0]
assert(diff in difficulties)
assert(difficulties[diff] in self._scores)
score = self._scores[difficulties[diff]]
score.max_acc.accuracy, score.max_acc.streak, score.max_acc.badnotes = struct.unpack('!fII', f.read(12))
score.max_streak.accuracy, score.max_streak.streak, score.max_streak.badnotes = struct.unpack('!fII', f.read(12))
except Exception as e:
sys.print_exception(e)
return self._scores
def saveScores(self):
try:
scoreFileName = os.path.join(os.path.dirname(self.fileName), ".score.pet")
with open(scoreFileName, "wb") as f:
f.write(b"PHSCORE\0")
diffs = tuple(filter(lambda x: not self._scores[x].empty(), self._scores.keys()))
f.write(bytes((len(diffs),)))
for diff in diffs:
score = self._scores[diff]
f.write(bytes((diff.id,)))
f.write(struct.pack("!fII", score.max_acc.accuracy, score.max_acc.streak, score.max_acc.badnotes))
f.write(struct.pack("!fII", score.max_streak.accuracy, score.max_streak.streak, score.max_streak.badnotes))
except Exception as e:
sys.print_exception(e)
def recordScore(self, difficulty, accuracy, streak, badnotes):
if self._scores is None:
self.readScores()
max_acc = self._scores[difficulty].max_acc
max_streak = self._scores[difficulty].max_streak
save = False
if max_acc.empty() or accuracy > max_acc.accuracy:
max_acc.accuracy = accuracy
max_acc.streak = streak
max_acc.badnotes = badnotes
save = True
elif accuracy == max_acc.accuracy:
if streak > max_acc.streak:
max_acc.streak = streak
max_acc.badnotes = badnotes
save = True
elif badnotes < max_acc.badnotes:
max_acc.badnotes = badnotes
save = True
if max_streak.empty() or streak > max_streak.streak:
max_streak.streak = streak
max_streak.accuracy = accuracy
max_streak.badnotes = badnotes
save = True
elif streak == max_streak.streak:
if accuracy > max_streak.accuracy:
max_streak.accuracy = accuracy
max_streak.badnotes = badnotes
save = True
elif badnotes < max_streak.badnotes:
max_streak.badnotes = badnotes
save = True
if save:
self.saveScores()
return save
def getName(self): def getName(self):
return self._get("name") return self._get("name")
...@@ -168,8 +290,14 @@ class SongInfo(object): ...@@ -168,8 +290,14 @@ class SongInfo(object):
return 0.1 return 0.1
return preview / length return preview / length
def getScores(self):
if self._scores is None:
self.readScores()
return self._scores
name = property(getName, setName) name = property(getName, setName)
artist = property(getArtist, setArtist) artist = property(getArtist, setArtist)
delay = property(getDelay, setDelay) delay = property(getDelay, setDelay)
difficulties = property(getDifficulties) difficulties = property(getDifficulties)
preview = property(getPreview) preview = property(getPreview)
scores = property(getScores)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment