Skip to content

Commit 1c139f1

Browse files
committed
Merge branch 'feature/academy' into develop
2 parents 24bd9e7 + f57834b commit 1c139f1

File tree

7 files changed

+1298
-0
lines changed

7 files changed

+1298
-0
lines changed

term_timer/methods/cases/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ def load_cases(path):
2323
'name': case_name,
2424
'main': data['main'],
2525
'probability': data['probability'],
26+
'probability_label': data['probability_label'],
2627
'setups': data['setups'],
28+
'masks': data['masks'],
2729
}
2830

2931
for mask, mask_info in data['masks'].items():

term_timer/server/app.py

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import gc
2+
import json
23
import os
34
import re
45
from datetime import datetime
@@ -39,6 +40,7 @@
3940
from term_timer.interface.console import console
4041
from term_timer.methods import METHOD_ANALYSERS
4142
from term_timer.methods.base import get_step_config
43+
from term_timer.methods.cases import CASES
4244
from term_timer.orientation import ORIENTATION_MOVES
4345
from term_timer.solve import Solve
4446
from term_timer.stats import Statistics
@@ -676,6 +678,160 @@ def __init__(self, cube, session, solve_id):
676678
redirect(f'/{ cube }/{ session }/')
677679

678680

681+
class AcademyView(View):
682+
template_name = 'academy/overview.html'
683+
methods = {
684+
'CFOP': {
685+
'name': 'CFOP',
686+
'description': (
687+
'Cross, F2L, OLL, PLL - The most popular speedcubing method'
688+
),
689+
'steps': {
690+
'F2L': {
691+
'name': 'F2L',
692+
'description': (
693+
'First Two Layers - '
694+
'Solve cross and first two layers simultaneously'
695+
),
696+
'description_alt': (
697+
'Solve the cross and first two layers simultaneously '
698+
'using corner-edge pairs.'
699+
),
700+
},
701+
'OLL': {
702+
'name': 'OLL',
703+
'description': (
704+
'Orientation of Last Layer - '
705+
'Orient all pieces on the last layer'
706+
),
707+
'description_alt': (
708+
'Orient all pieces on the last layer '
709+
'to show the same color on top.'
710+
),
711+
},
712+
'PLL': {
713+
'name': 'PLL',
714+
'description': (
715+
'Permutation of Last Layer - '
716+
'Permute all pieces on the last layer'
717+
),
718+
'description_alt': (
719+
'Permute all pieces on the last layer '
720+
'to their correct positions.'
721+
),
722+
},
723+
},
724+
},
725+
}
726+
727+
def get_context(self):
728+
return {
729+
'methods': self.methods,
730+
}
731+
732+
733+
class AcademyStepView(AcademyView):
734+
template_name = 'academy/step.html'
735+
736+
def __init__(self, step):
737+
self.step = step.upper()
738+
739+
try:
740+
self.cases_data = CASES[self.step]
741+
except KeyError:
742+
abort(404, f'{ self.step } does not exist')
743+
744+
def get_context(self):
745+
cases = []
746+
747+
for case_id, case_data in self.cases_data.items():
748+
case_info = {
749+
'id': case_id,
750+
'name': case_data['name'],
751+
'main_algorithm': case_data['main'],
752+
'masks_count': len(case_data['masks']),
753+
}
754+
if self.step == 'OLL':
755+
try:
756+
case_info['code'], case_info['name'], _ = parse_case_name(
757+
case_data['name'], self.step,
758+
)
759+
except:
760+
case_info['code'] = case_id
761+
case_info['name'] = case_id
762+
elif self.step == 'PLL':
763+
case_info['code'] = case_id
764+
case_info['name'] = f'PLL {case_id}'
765+
elif self.step == 'F2L':
766+
case_info['code'] = case_id
767+
case_info['name'] = f'F2L {case_id}'
768+
769+
cases.append(case_info)
770+
771+
return {
772+
'step': self.step,
773+
'step_info': self.methods['CFOP']['steps'][self.step],
774+
'cases': cases,
775+
'cases_count': len(cases),
776+
}
777+
778+
779+
class AcademyCaseView(AcademyView):
780+
template_name = 'academy/case.html'
781+
782+
def __init__(self, step, case_id):
783+
self.step = step.upper()
784+
self.case_id = case_id
785+
786+
try:
787+
self.case_data = CASES[self.step][self.case_id]
788+
except KeyError:
789+
abort(404, f'{ self.step } { self.case_id } does not exist')
790+
791+
def get_context(self):
792+
case_info = {
793+
'id': self.case_id,
794+
'name': self.case_id,
795+
'main_algorithm': self.case_data['main'],
796+
'probability': self.case_data['probability_label'],
797+
}
798+
799+
if self.step == 'OLL':
800+
try:
801+
case_info['code'], case_info['name'], _ = parse_case_name(self.case_id, self.step)
802+
except:
803+
case_info['code'] = self.case_id
804+
case_info['name'] = self.case_id
805+
elif self.step == 'PLL':
806+
case_info['code'] = self.case_id
807+
case_info['name'] = f'PLL {self.case_id}'
808+
elif self.step == 'F2L':
809+
case_info['code'] = self.case_id
810+
case_info['name'] = f'F2L {self.case_id}'
811+
812+
# Process masks for different orientations
813+
orientations = []
814+
masks = self.case_data.get('masks', {})
815+
for mask, aufs in masks.items():
816+
orientations.append({
817+
'mask': mask,
818+
'aufs': aufs,
819+
})
820+
821+
# Process setup algorithms
822+
setups = self.case_data.get('setups', [])
823+
824+
return {
825+
'step': self.step,
826+
'step_info': self.methods['CFOP']['steps'][self.step],
827+
'case': case_info,
828+
'orientations': orientations,
829+
'orientations_count': len(orientations),
830+
'setups': setups,
831+
'setups_count': len(setups),
832+
}
833+
834+
679835
class Server:
680836

681837
def run_server(self, host, port, debug):
@@ -720,6 +876,18 @@ def add_trailing_slash():
720876
def session_list():
721877
return SessionListView().as_view(debug)
722878

879+
@app.route('/academy/')
880+
def academy_overview():
881+
return AcademyView().as_view(debug)
882+
883+
@app.route('/academy/<step>/')
884+
def academy_step(step):
885+
return AcademyStepView(step).as_view(debug)
886+
887+
@app.route('/academy/<step>/<case_id>/')
888+
def academy_case(step, case_id):
889+
return AcademyCaseView(step, case_id).as_view(debug)
890+
723891
@app.route('/<cube:int>/<session:path>/<solve:int>/update/',
724892
method='POST')
725893
def solve_update(cube, session, solve):

0 commit comments

Comments
 (0)