Added level sorting to songselect.py

Frank Foeth foeth01 at orange.nl
Thu Jan 18 06:56:43 EST 2007


Hallo,

I'm new to this list. Please find below a patch for the current
songselect.py file. It adds a level sorting mode. The goal is to 
supply the user with a list of folders containing songs that contain
a dance at the specified level. In the folders the songs are sorted by
difficulty category (e.g. "BEGINNER", "LIGHT", "BASIC"), and further
subsorted with grade and rank or bpm. 

Level sorting is not straightforward, as songs have multiple levels, so 
it requires some extra code for sorting a folder. Furthermore, level
sorting is impossible if only one folder is allowed (because of multiple
dances per song), so level sorting has to be added or removed during
SongSelect's initialization.
 
Known problems in "level" sorting: 
1. When changing sortmodes with a song (not a folder) "under the
selection cursor" and inbetween changing the selected song in a 
non-level sorted folder, the level folder you eventually end up in is 
not well defined. I don't see a way to remedy this, but the weird way to
produce this behaviour probably warrants not many users will file bug
reports.
2. It is currently not possible to automatically return to level mode
upon restarting the program. This is easily remedied, but requires
touching another module: constants.py (line 137).
3. The use of the SongDisplayItem.info["tmpsortdata"] is ugly, as it
spill over in to the song's data. It should be remedied by adding a
parameter to SongDisplayItem (I hope I've got the name right, I'm doing
typing this part from memory), e.g. SongDisplayItem.level_sort_data =
"" . 

The reason I did not do 2. and 3. yet is to limit the patch to one
file. 

I'd like some comments. And if it's good enough could Pavel please add
it to the repository.

Yours,
Frank Foeth

------------------------------songselect.patch--------------------
12a13
> import util
31c32,35
<                         SORTS["title"](x, y)))
---
>                         SORTS["title"](x, y))),
>   "level": (lambda x, y: cmp(str(x.info["tmpsortdata"]).lower(),
>                                 str(y.info["tmpsortdata"]).lower()) or
>                             SORTS["title"](x,y))
34c38
< SORT_NAMES = ["mix", "title", "artist", "bpm"]
---
> SORT_NAMES = ["mix", "title", "artist", "bpm", "level"]
37a42,49
> # Known problems in "level" sorting: 
> # 1. When changing sortmodes with a song (not a folder) "under the
> # selection cursor" and inbetween changing the selected song in a 
> # non-level sorted folder, the level folder you eventually end up in
is 
> # not well defined.
> # 2. It is currently not possible to automatically return to level
mode upon
> # restarting the program.
> 
137c149
< 
---
>     
151a164
>     global SORT_NAMES, NUM_SORTS
152a166,171
>       # As songs have many levels a level sort over a single folder
is 
>       # meaningless, therefore level sorting should only take place
when 
>       # "folders" are allowed. "Folders" is an "interface option".
>       if not "level" in SORT_NAMES:
>         SORT_NAMES.append("level")
>         NUM_SORTS = len(SORT_NAMES)
154c173
<       name = SORT_NAMES[mainconfig["sortmode"]]
---
>       name = SORT_NAMES[mainconfig["sortmode"] % NUM_SORTS]
156a176,178
>       if "level" in SORT_NAMES:
>         SORT_NAMES.remove("level")
>         NUM_SORTS = len(SORT_NAMES)        
362a385
>     levels = {}
392c415,426
< 
---
>         
>       if "level" in SORT_NAMES :
>         for difficulty in s.difficulty[self._game].values():
>           label = "%2d" % difficulty
>           if not label in levels: levels[label]=[]
>           levels[label].append(s)
>           # s.folder["level"] is only initialised here.
>           if "level" in s.folder.keys():
>             s.folder["level"] = min(s.folder["level"], label) 
>           else:
>             s.folder["level"] = label
>         
394c428,430
<                       "bpm": bpms }
---
>                       "bpm": bpms}
>     if "level" in SORT_NAMES :
>       self._folders["level"] = levels
408a445
>     # folder contains a sorting criterium value in string format
411c448,473
<     songlist.sort(SORTS[sort])
---
>     
>     if sort == "level": 
>       # "BASIC", "LIGHT", etc. based subsort, 
>       # using the sorted difficulty list from util
>       difficulty_index_map = dict((util.DIFFICULTY_LIST[i],i) \
>                               for i in
range(len(util.DIFFICULTY_LIST)))
>       for s in songlist:
>         s.folder["level"] = folder # for consistency, obligatory
>         for difficulty in s.difficulty[self._game].keys():
>           if s.difficulty[self._game][difficulty] == int(folder):
>             s.info["tmpsortdata"] = str("%2d" %
difficulty_index_map[difficulty])
>             # adding some extras to refine the sorting with grades
>             rank = records.get(s.info["recordkey"], difficulty,
self._game)[0]
>             grade =
grades.grades[self._config["grade"]].grade_by_rank(rank)
>             if grade in ['?','F']:
>               s.info["tmpsortdata"] += " %s%d %5.1f" % (grade[0], 
>                                              5-len(grade),
s.info["bpm"])
>               # rank: the same for all '?' and all 'F', so useless for
sorting; 
>               # bpm: at least often faster bpm is more difficult
>               #  (as a difficulty measure it isn't very reliable
though)
>             else:
>               s.info["tmpsortdata"] += " %s%d %f" % (grade[0], 
>                                              5-len(grade), 1.0 - rank)
>               # AAAA is converted to A1 to sort it before A which
converts to A4
>               # rank should be sorted decendingly
>             break
412a475,476
>     songlist.sort(SORTS[sort])
>     






More information about the pyddr-devel mailing list