65
65
# Each modern Etterna XML usually has up to 6 sections (in a single giant <Stats> section)
66
66
# These sections are always in this order:
67
67
# GeneralData, Favorites, Permamirror, Playlists, ScoreGoals, PlayerScores
68
- # We want to merge the XMLs to produce a super XML of both while hopefully staying consistent
69
- # in terms of keeping certain TopScore values with scores. That'll be the hardest part .
68
+ # We want to merge the XMLs to produce a super XML of both. The client can sanitize the scores
69
+ # as long as they are placed in the correct location, as TopScore and the SSRs are recalculated on startup .
70
70
71
71
def findSection (xml , sectionName ):
72
72
''' Find a section of the XML by name. Return None if no section exists.'''
@@ -77,6 +77,10 @@ def findSection(xml, sectionName):
77
77
78
78
# GeneralData. This contains literally general data and info about the profile.
79
79
# I'm expecting this to be already filled out so I won't mess with it.
80
+ e_generaldata = findSection (e , "GeneralData" )
81
+ if e_generaldata is None :
82
+ print ("The first XML is missing general data so I quit." )
83
+ exit ()
80
84
81
85
# Favorites. This contains a list of chartkeys as tag endings, simply enough.
82
86
# We can merge this.
@@ -211,47 +215,79 @@ def findSection(xml, sectionName):
211
215
# This is the largest and most important piece of information.
212
216
# Merging this is very tough.
213
217
# Consider: Each score is organized by Chart Key. Beyond that, it is organized by lists of scores at a rate.
214
- # Each score has a TopScore status. This status is likely to change (and should be recalculated by the game anyways)
215
- # Due to astronomical amounts of laziness, I have chosen to just cram the elements all into one pile.
216
- # (and also filter out duplicates in the process)
217
- all_scores = {}
218
+
219
+ all_scores = {} # by chartkey
218
220
e_score_section = findSection (e , "PlayerScores" )
219
221
e2_score_section = findSection (e2 , "PlayerScores" )
220
222
223
+ all_score_keys = set () # by scorekey
221
224
if e_score_section is not None :
222
225
print ("Main xml score size" , len (e_score_section ))
223
226
for chart in list (e_score_section ):
224
227
key = chart .attrib ["Key" ]
225
228
if key not in all_scores :
226
- all_scores [key ] = chart
229
+ all_scores [key ] = {}
230
+ for scoresat in list (chart ):
231
+ all_scores [key ][scoresat .attrib ["Rate" ]] = scoresat
232
+ for score in list (scoresat ):
233
+ all_score_keys .add (score .attrib ["Key" ])
227
234
else :
228
235
for scoresat in list (chart ):
229
- all_scores [key ].append (scoresat )
236
+ rate = scoresat .attrib ["Rate" ]
237
+ if rate in all_scores [key ]:
238
+ for score in list (scoresat ):
239
+ if score .attrib ["Key" ] in all_score_keys :
240
+ continue
241
+ all_score_keys .add (score .attrib ["Key" ])
242
+ ggg = xml .etree .ElementTree .SubElement (all_scores [key ][rate ], "Score" , attrib = {"Key" : score .attrib ["Key" ]})
243
+ ggg .extend (score )
244
+ else :
245
+ all_scores [key ][scoresat .attrib ["Rate" ]] = scoresat
246
+ for score in list (scoresat ):
247
+ all_score_keys .add (score .attrib ["Key" ])
248
+
230
249
231
250
if e2_score_section is not None :
232
251
print ("Second xml score size" , len (e2_score_section ))
233
252
for chart in list (e2_score_section ):
234
253
key = chart .attrib ["Key" ]
235
254
if key not in all_scores :
236
- all_scores [key ] = chart
255
+ all_scores [key ] = {}
256
+ for scoresat in list (chart ):
257
+ all_scores [key ][scoresat .attrib ["Rate" ]] = scoresat
258
+ for score in list (scoresat ):
259
+ all_score_keys .add (score .attrib ["Key" ])
237
260
else :
238
261
for scoresat in list (chart ):
239
- all_scores [key ].append (scoresat )
262
+ rate = scoresat .attrib ["Rate" ]
263
+ if rate in all_scores [key ]:
264
+ for score in list (scoresat ):
265
+ if score .attrib ["Key" ] in all_score_keys :
266
+ continue
267
+ all_score_keys .add (score .attrib ["Key" ])
268
+ ggg = xml .etree .ElementTree .SubElement (all_scores [key ][rate ], "Score" , attrib = {"Key" : score .attrib ["Key" ]})
269
+ ggg .extend (score )
270
+ else :
271
+ all_scores [key ][scoresat .attrib ["Rate" ]] = scoresat
272
+ for score in list (scoresat ):
273
+ all_score_keys .add (score .attrib ["Key" ])
240
274
e3_score_section = None
241
275
if len (all_scores ) > 0 :
242
276
e3_score_section = xml .etree .ElementTree .Element ("PlayerScores" )
243
- for chart_element in all_scores .values ():
244
- e3_score_section .append (chart_element )
245
- print ("Final xml score size" , len (e3_score_section ))
246
-
277
+ for chartkey , scoresat in all_scores .items ():
278
+ cnode = xml .etree .ElementTree .SubElement (e3_score_section , "Chart" )
279
+ cnode .attrib ["Key" ] = chartkey
280
+ for rate , scores in scoresat .items ():
281
+ satnode = xml .etree .ElementTree .SubElement (cnode , "ScoresAt" )
282
+ satnode .attrib ["Rate" ] = rate
283
+ for s in list (scores ):
284
+ snode = xml .etree .ElementTree .SubElement (satnode , "Score" , attrib = {"Key" : s .attrib ["Key" ]})
285
+ snode .extend (s )
286
+ print ("Final xml score size" , len (e3_score_section ))
247
287
248
288
249
289
# Outputting the xml.
250
290
root = xml .etree .ElementTree .Element ("Stats" )
251
- e_generaldata = findSection (e , "GeneralData" )
252
- if e_generaldata is None :
253
- print ("The first XML is missing general data so I quit." )
254
- exit ()
255
291
256
292
root .append (e_generaldata )
257
293
if favorites_Element is not None :
0 commit comments