Specify paths correctly
[GrooveNet.git] / ScoreSync.sh
1 #!/bin/bash
2
3 DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
4 source "$DIR/config.sh"
5
6 if [ -z $1 ]; then
7 exit
8 fi
9
10 songs_file=$(ls "$DIR" | grep songs | tail -n1)
11
12 if [ -z "$songs_file" ]; then
13 exit
14 fi
15
16 sed -i '1s/.*/<?xml version="1.0" encoding="ISO-8859-1" ?>/' "${path_to_stats}"
17 difficulties=(Challenge Edit Hard Medium Easy)
18 step_types=("dance-double" "dance-single")
19 tiers=("1.00" "0.99" "0.98" "0.96" "0.94" "0.92" "0.89" "0.86" "0.83" "0.80" "0.76" "0.72" "0.68" "0.64" "0.60" "0.55")
20
21 if [ "$1" = "push" ]; then
22 declare -A all_song_hashes
23 declare -A hash_map
24
25 # pretty sure this can be merged with the shit below somehow
26 if find "${DIR}"/*.favourites.txt -type f -print -quit 2>/dev/null | grep -q .; then
27 pattern=""
28 while read -d $'\0' file; do
29 IFS=$'\n' read -d '' -r -a lines < $file
30 basename=$(basename "$file")
31 person="${basename%.*.*}"
32 if [ "$person" = "$me" ]; then
33 persons_folder="$faves_folder"
34 else
35 formatted_person="$(tr '[:lower:]' '[:upper:]' <<< ${person:0:1})${person:1}"
36 persons_folder=${external_favourite_naming_scheme/\%person\%/$formatted_person}
37 fi
38 for i in "${lines[@]}"; do
39 all_song_hashes["$i"]+="$persons_folder"
40 pattern="${pattern}|$i"
41 done
42 done < <(find "${DIR}"/*.favourites.txt -type f -print0)
43 fi
44
45 pattern="${pattern:1}"
46 song_paths=$(grep -E "$pattern" "${DIR}/${songs_file}" | sort -u -k1,1)
47
48 while read -r song_path; do
49 hash=$(echo $song_path | cut -sd ' ' -f1)
50 path=$(echo $song_path | cut -sd / -f6 )
51 hash_map["${all_song_hashes[$hash]}/$path"]+="$hash"
52 done <<< "$song_paths"
53
54 if find "${DIR}"/*.favourites.txt -type f -print -quit 2>/dev/null | grep -q .; then
55 while read -d $'\0' file; do
56 file=$(basename "$file")
57
58 IFS=$'\n' read -d '' -r -a lines < "${DIR}/$file"
59 person="${file%.*.*}"
60 if [ "$person" = "$me" ]; then
61 persons_folder="$faves_folder"
62 else
63 formatted_person="$(tr '[:lower:]' '[:upper:]' <<< ${person:0:1})${person:1}"
64 persons_folder=${external_favourite_naming_scheme/\%person\%/$formatted_person}
65 fi
66
67 xmlstarlet_meta_cmd="$xmlstarlet_meta_cmd -v \"//SongScores//Song[starts-with(@Dir, \\\"Songs/${persons_folder}\\\")][Steps//PercentDP]//@*\" -n"
68 xmlstarlet_scores_cmd="$xmlstarlet_scores_cmd -o \"SCORES\" -n -v \"//SongScores//Song[starts-with(@Dir, \\\"Songs/${persons_folder}\\\")]//HighScore[1]//PercentDP\" -n -o \"NAMES\" -n -v \"//SongScores/Song[starts-with(@Dir, \\\"Songs/${persons_folder}\\\")]//HighScore[1]//Name\" -n"
69 done < <(find "${DIR}"/*.favourites.txt -type f -print0)
70
71 meta=$(eval "xmlstarlet sel -I -t $xmlstarlet_meta_cmd -o \"Songs\" \"${path_to_stats}\"")
72 scores=$(eval "xmlstarlet sel -I -t $xmlstarlet_scores_cmd \"${path_to_stats}\"")
73 nulls=$(eval "xmlstarlet sel -t -v \"//LastPlayed[text()=\\\"1933-01-02\\\"]/ancestor::Song/@Dir\" \"${path_to_stats}\"")
74
75 declare -a null_hashes
76
77 if ! [ -z "$nulls" ]; then
78 while read -r null; do
79 the_path=$(echo "$null" | cut -sd / -f2,3 | sed 's/&amp;/\&/g; s/&lt;/\</g; s/&gt;/\>/g; s/&quot;/\"/g; s/&apos;/\'"'"'/g')
80 if ! [ -z "${hash_map[$the_path]}" ]; then
81 null_hashes+=("${hash_map[$the_path]}")
82 fi
83 done <<< "$nulls"
84 fi
85
86 new_song=false
87 song_hash=""
88 declare -a d
89 declare -a t
90 counter=0
91 bigboi_counter=0
92 declare -A mmeta
93 declare -a sscores
94 declare -a names
95
96 scores_or_names="SCORES"
97
98 while read -r s; do
99 if [ "$s" = "SCORES" ]; then
100 scores_or_names="SCORES"
101 continue
102 fi
103
104 if [ "$s" = "NAMES" ]; then
105 scores_or_names="NAMES"
106 continue
107 fi
108
109 if ! [ "$scores_or_names" = "SCORES" ]; then
110 sscores+=($s)
111 continue
112 fi
113
114 if ! [ "$scores_or_names" = "NAMES" ]; then
115 names+=($s)
116 continue
117 fi
118 done <<< "$scores"
119
120 while read -r m; do
121 if [[ ${m:0:5} = "Songs" ]]; then
122 for dd in "${!d[@]}"; do
123 if ! [ -z "${mmeta["${song_hash}:${d[$dd]}:${t[$dd]}"]}" ]; then
124 echo "!!!! that key exists already..."
125 fi
126
127 mmeta["${song_hash}:${d[$dd]}:${t[$dd]}"]="${names[$bigboi_counter]}:${sscores[$bigboi_counter]}"
128 bigboi_counter=$((bigboi_counter+1))
129 done
130
131 d=()
132 t=()
133 counter=0
134 if [[ ${m:0:6} = "Songs/" ]]; then
135 plain_song=$(echo $m | sed 's/&amp;/\&/g;' | cut -sd / -f2,3)
136 song_hash=${hash_map[$plain_song]}
137 fi
138 continue
139 fi
140
141 if (( $counter % 2 )); then
142 t+=($m)
143 else
144 d+=($m)
145 fi
146 counter=$((counter+1))
147 done <<< "$meta"
148
149 # this is a list of all hashes and who has the score on them
150 # todo: go over this list, and apply the following:
151 # remove the hash from all_song_hashes and:
152 # if I have a score on it, add it to writeout
153 # if someone else has the score on it add it to writeout with NODATA
154 # if it is in null nodes (need to write code for this) add it to writeout with NODATA
155 # all_song_hashes should now have the information we need to retrieve the song from elsewhere in stats.xml
156 declare -A nodatas
157 writeout="${me_highscore_name}"
158 for fuck in "${!mmeta[@]}"; do
159 the_score=$(echo ${mmeta[$fuck]} | cut -sd : -f1)
160 the_scorer=$(echo ${mmeta[$fuck]} | cut -sd : -f2)
161 just_hash=$(echo $fuck | cut -sd : -f1)
162
163 if [ "$the_scorer" = "$me_highscore_name" ] || [ "$the_scorer" = "EVNT" ]; then
164 writeout="$writeout\n${fuck}:${the_score}"
165 else
166 if [ -z "${nodatas["${just_hash}"]}" ]; then
167 writeout="$writeout\n${just_hash}:NODATA"
168 nodatas["${just_hash}"]="${just_hash}"
169 fi
170 fi
171 unset all_song_hashes["$just_hash"]
172 #echo "$fuck $the_score $the_scorer"
173 done
174
175 for shit in "${null_hashes[@]}"; do
176 unset all_song_hashes["$shit"]
177 writeout="$writeout\n${shit}:NODATA"
178 done
179
180 # now all that's needed is to locate the data for these nodes (they are ones that were faved this session, so cannot exist in stats.xml for the remainder of the sesh)
181 # TODO: Technically these queries are not quite specific enough. They could find scores left by players other than the machine owner
182 # but probably it's fine
183 for fuck in "${!all_song_hashes[@]}"; do
184 pathh=$(cat "${DIR}/${songs_file}" | grep $fuck | cut -sd / -f5,6 )
185 pathh=$(echo $pathh | sed 's/`/\\\`/g')
186 xmlstarlet_orphans_cmd="$xmlstarlet_orphans_cmd -i \"//SongScores//Song[@Dir=\\\"Songs/${pathh}/\\\"]//Steps//HighScore[1]//PercentDP\" \
187 -o \"SONG:${fuck}\" -n \
188 -o \"STEPTYPES\" -n \
189 -v \"//SongScores//Song[@Dir=\\\"Songs/${pathh}/\\\"]//Steps//HighScore//PercentDP/ancestor::Steps/@StepsType\" -n \
190 -o \"DIFFICULTIES\" -n \
191 -v \"//SongScores//Song[@Dir=\\\"Songs/${pathh}/\\\"]//Steps//HighScore//PercentDP/ancestor::Steps/@Difficulty\" -n \
192 -o \"SCORES\" -n \
193 -v \"//SongScores//Song[@Dir=\\\"Songs/${pathh}/\\\"]//Steps//HighScore[1]//PercentDP\" -n \
194 --else \
195 -o \"SONG:${fuck}\" -n \
196 -o \"NOSCORES\" -n \
197 --break"
198 done
199
200 if ! [ -z "$xmlstarlet_orphans_cmd" ]; then
201 scores_living_elsewhere=$(eval "xmlstarlet sel -t $xmlstarlet_orphans_cmd -o \"SONG\" \"${path_to_stats}\"")
202 IFS=$'\n' read -rd '' -a scores_elsewhere <<<"$scores_living_elsewhere"
203
204 declare -a jjj_types
205 declare -a jjj_diffs
206 declare -a jjj_scores
207 past_steptypes=false
208 past_difficulties=false
209 past_scores=false
210 no_dump=false
211 for i in "${scores_elsewhere[@]}"; do
212 if [[ ${i:0:4} = "SONG" ]]; then
213 if [ "$no_dump" = false ]; then
214 for j in "${!jjj_types[@]}"; do
215 writeout="${writeout}\n${jjj_hash}:${jjj_diffs[$j]}:${jjj_types[$j]}:${jjj_scores[$j]}"
216 done
217 else
218 writeout="${writeout}\n${jjj_hash}:NODATA"
219 fi
220
221 jjj_types=()
222 jjj_diffs=()
223 jjj_scores=()
224 past_steptypes=false
225 past_difficulties=false
226 past_scores=false
227 no_dump=false
228 jjj_hash=$(echo $i | cut -sd ':' -f2)
229 continue
230 fi
231
232 if [ "$i" = "NOSCORES" ]; then
233 no_dump=true
234 continue
235 fi
236
237 if [ "$i" = "STEPTYPES" ]; then
238 past_steptypes=true
239 continue
240 fi
241
242 if [ "$i" = "DIFFICULTIES" ]; then
243 past_difficulties=true
244 continue
245 fi
246
247 if [ "$i" = "SCORES" ]; then
248 past_scores=true
249 continue
250 fi
251
252 if [ "$past_scores" = true ]; then
253 jjj_scores+=("$i")
254 continue
255 fi
256
257 if [ "$past_difficulties" = true ]; then
258 jjj_diffs+=("$i");
259 continue
260 fi
261
262 if [ "$past_steptypes" = true ]; then
263 jjj_types+=("$i")
264 continue
265 fi
266 done
267 fi
268 echo -e "$writeout" > "${DIR}/$me.scores.txt"
269 scp "$DIR/$me.scores.txt" groovenet@cameron1729.xyz:/mnt/media/GrooveNet
270 fi
271 fi
272
273 if [ "$1" = "apply" ]; then
274 declare -A all_song_hashes
275 declare -A scores
276 declare -a all_scores
277 declare -a bros
278 declare -A pranks
279 declare -A hash_map
280 declare -A null_files
281 xmlstarlet_deletes=""
282 xmlstarlet_orphans_cmd=""
283
284 pattern=""
285 if find "${DIR}"/*.favourites.txt -type f -print -quit 2>/dev/null | grep -q .; then
286 while read -d $'\0' file; do
287 IFS=$'\n' read -d '' -r -a lines < $file
288 basename=$(basename "$file")
289 person="${basename%.*.*}"
290 for i in "${lines[@]}"; do
291 all_song_hashes["$i"]+="$person"
292 pattern="${pattern}|$i"
293 done
294 done < <(find "${DIR}"/*.favourites.txt -type f -print0)
295 fi
296
297 pattern="${pattern:1}"
298 song_paths=$(grep -E "$pattern" "${DIR}/${songs_file}" | sort -u -k1,1)
299
300 while read -r song_path; do
301 hash=$(echo $song_path | cut -sd ' ' -f1)
302 path=$(echo $song_path | cut -sd / -f5-6 )
303 hash_map["$hash"]+="$path"
304 done <<< "$song_paths"
305
306 bros=("$me_highscore_name")
307 if find "${DIR}"/*.scores.txt -type f -print -quit 2>/dev/null | grep -q .; then
308 while read -d $'\0' file; do
309 basename=$(basename "$file")
310 person="${basename%.*.*}"
311
312 if [ "$person" = "$me" ]; then
313 persons_folder="$faves_folder"
314 else
315 formatted_person="$(tr '[:lower:]' '[:upper:]' <<< ${person:0:1})${person:1}"
316 persons_folder=${external_favourite_naming_scheme/\%person\%/$formatted_person}
317 fi
318 song_dir="Songs/$persons_folder"
319 xmlstarlet_deletes="-d \"//SongScores//Song[starts-with(@Dir, \\\"${song_dir}\\\")]\" ${xmlstarlet_deletes}"
320
321 IFS=$'\n' read -d '' -r -a lines < $file
322 highscorename=${lines[0]}
323 bros+=("$highscorename")
324 for i in "${lines[@]:1}"; do
325 if [ "$(echo $i | cut -sd : -f2)" = "NODATA" ]; then
326 # null files is used to store whether or not an attempt to copy this song from its old location in stats.xml was made
327 # the way it works is:
328 # after a files score is copied over from stats.xml - it will either have a real node in stats.xml or a
329 # null placeholder one (see further down)
330 # in the push command, null nodes get written to scores.txt as hash:NODATA
331 # so the next time apply runs, we know that they had already been copied over, and we don't have to run
332 # xmlstarlet again
333
334 # Then later on when we process the pranks, unset any hashes that turn out to have a score elsewhere
335 # before finally adding the null nodes
336 if [ "$person" = "$me" ]; then
337 # this represents files that __should not__ be copied, that is, we know they have nothing in stats.xml at their original location
338 null_files[$(echo $i | cut -sd : -f1)]+="$person"
339 fi
340 else
341 song_score=$(echo $i | rev | cut -sd : -f1 | rev)
342 song_steps_type=$(echo $i | rev | cut -sd : -f2 | rev)
343 song_difficulty=$(echo $i | rev | cut -sd : -f3 | rev)
344 song_hash=$(echo $i | rev | cut -sd : -f4 | rev)
345 scores["${highscorename}:${song_hash}:${song_difficulty}:${song_steps_type}"]+="${song_score}"
346 all_scores+=("${song_hash}:${song_difficulty}:${song_steps_type}")
347 fi
348 done
349 done < <(find "${DIR}"/*.scores.txt -type f -print0)
350 fi
351
352 # instead of using all_score_unique, use the all song hashes list
353 # that way when we come across something with no score we can build up a query for xmlstarlet
354 # for each hash
355 # for each difficulty
356 # for each step type
357 # do the bros algorithm
358 # need a flag to decide if the hash has a score,
359 # if it doesn,t add it it to the list of hashes to attempt to copy a score from
360 declare -a orphans
361 for hash in "${!all_song_hashes[@]}"; do
362 had_score=false
363 for d in "${difficulties[@]}"; do
364 for t in "${step_types[@]}"; do
365 highest=""
366 for b in "${bros[@]}"; do
367 if [ -z "$highest" ]; then
368 highest="$b"
369 else
370 i="${hash}:${d}:${t}"
371 if [ -z "${scores[${b}:${i}]}" ]; then
372 scores["${b}:${i}"]+="0.000000"
373 fi
374
375 if [ -z "${scores[${highest}:${i}]}" ]; then
376 scores["${highest}:${i}"]+="0.000000"
377 fi
378
379 if [ 1 -eq "$(echo "${scores[${b}:${i}]} > ${scores[${highest}:${i}]}" | bc)" ]; then
380 highest="$b"
381 fi
382 fi
383 done
384 if ! [ "${scores[${highest}:${i}]}" = "0.000000" ]; then
385 pranks["${i}"]+="${highest}:${scores[${highest}:${i}]}"
386
387 # We found a score for this in someone else's scores file, a proper node will be made.
388 if ! [ -z "${null_files[$hash]}" ]; then
389 unset null_files["$hash"]
390 fi
391 had_score=true
392 fi
393 done
394 done
395
396 # TODO: Really this should happen __before__ the bros algorithm (and the unset from the bros algorithm should be removed)
397 # that way any scores I have locally for something a friend faved, will be considered. As it stands, scores from a friends
398 # scores.txt will always trump anything I have in the original directory
399 # only try find files for which there is actually nothing in scores.txt
400 if [ "$had_score" = false ] && [ -z "${null_files[${hash}]}" ]; then
401 echo "$hash had no score and is not in nulls"
402 song="${hash_map[${hash}]}"
403 song=$(echo $song | sed 's/`/\\\`/g')
404 xmlstarlet_orphans_cmd="$xmlstarlet_orphans_cmd -i \"//SongScores//Song[@Dir=\\\"Songs/${song}/\\\"]//Steps//HighScore[1]//PercentDP\" \
405 -o \"SONG:${hash}\" -n \
406 -o \"STEPTYPES\" -n \
407 -v \"//SongScores//Song[@Dir=\\\"Songs/${song}/\\\"]//Steps//HighScore//PercentDP/ancestor::Steps/@StepsType\" -n \
408 -o \"DIFFICULTIES\" -n \
409 -v \"//SongScores//Song[@Dir=\\\"Songs/${song}/\\\"]//Steps//HighScore//PercentDP/ancestor::Steps/@Difficulty\" -n \
410 -o \"SCORES\" -n \
411 -v \"//SongScores//Song[@Dir=\\\"Songs/${song}/\\\"]//Steps//HighScore[1]//PercentDP\" -n \
412 --else \
413 -o \"SONG:${hash}\" -n \
414 -o \"NOSCORES\" -n \
415 --break"
416 orphans+=("$hash")
417 fi
418 done
419
420 scores_living_elsewhere=$(eval "xmlstarlet sel -t $xmlstarlet_orphans_cmd -o \"SONG\" \"${path_to_stats}\"")
421 IFS=$'\n' read -rd '' -a scores_elsewhere <<<"$scores_living_elsewhere"
422
423 empty_nodes=""
424 declare -a jjj_types
425 declare -a jjj_diffs
426 declare -a jjj_scores
427 past_steptypes=false
428 past_difficulties=false
429 past_scores=false
430 no_dump=false
431 for i in "${scores_elsewhere[@]}"; do
432 if [[ ${i:0:4} = "SONG" ]]; then
433 if [ "$no_dump" = false ]; then
434 for j in "${!jjj_types[@]}"; do
435 pranks["${jjj_song}:${jjj_diffs[$j]}:${jjj_types[$j]}"]+="${me_highscore_name}:${jjj_scores[$j]}"
436 done
437 fi
438
439 jjj_types=()
440 jjj_diffs=()
441 jjj_scores=()
442 past_steptypes=false
443 past_difficulties=false
444 past_scores=false
445 no_dump=false
446 jjj_song=$(echo $i | cut -sd ':' -f2)
447 continue
448 fi
449
450 if [ "$i" = "NOSCORES" ]; then
451 faver="${all_song_hashes[${jjj_song}]}"
452
453 if [ "$faver" = "$me" ]; then
454 persons_folder="$faves_folder"
455 else
456 formatted_person="$(tr '[:lower:]' '[:upper:]' <<< ${faver:0:1})${faver:1}"
457 persons_folder=${external_favourite_naming_scheme/\%person\%/$formatted_person}
458 fi
459
460 path="$(echo ${hash_map[${jjj_song}]} | cut -sd / -f2)"
461 path=$(echo $path | sed 's/&/\&amp;/g; s/</\&lt;/g; s/>/\&gt;/g; s/"/\&quot;/g; s/'"'"'/\&apos;/g')
462 song_path="Songs/${persons_folder}/${path}/"
463 empty_nodes="${empty_nodes}\n<Song Dir=\"$song_path\" >\
464 \n<Steps Difficulty=\"Challenge\" StepsType=\"dance-single\">\
465 \n<HighScoreList>\
466 \n<LastPlayed>1933-01-02</LastPlayed>\
467 \n<NumTimesPlayed>1</NumTimesPlayed>\
468 \n</HighScoreList>\
469 \n</Steps>\
470 \n</Song>"
471 no_dump=true
472 continue
473 fi
474
475 if [ "$i" = "STEPTYPES" ]; then
476 past_steptypes=true
477 continue
478 fi
479
480 if [ "$i" = "DIFFICULTIES" ]; then
481 past_difficulties=true
482 continue
483 fi
484
485 if [ "$i" = "SCORES" ]; then
486 past_scores=true
487 continue
488 fi
489
490 if [ "$past_scores" = true ]; then
491 jjj_scores+=("$i")
492 continue
493 fi
494
495 if [ "$past_difficulties" = true ]; then
496 jjj_diffs+=("$i");
497 continue
498 fi
499
500 if [ "$past_steptypes" = true ]; then
501 jjj_types+=("$i")
502 continue
503 fi
504 done
505
506 declare -A processed_pranks
507 new_nodes=""
508 for j in "${!pranks[@]}"; do
509 if [ -z "${processed_pranks[$j]}" ]; then
510 echo "$j :: ${pranks[$j]}"
511 song_pranker=$(echo "${pranks[$j]}" | cut -sd : -f1)
512 song_score=$(echo "${pranks[$j]}" | cut -sd : -f2)
513 song_steps_type=$(echo $j | cut -sd : -f3)
514 song_difficulty=$(echo $j | cut -sd : -f2)
515 song_faver=${all_song_hashes[$(echo $j | cut -sd : -f1)]}
516 song_hash=$(echo $j | cut -sd : -f1)
517 song_tier=1
518 for tier in "${tiers[@]}"; do
519 if [ 1 -eq "$(echo "$song_score < ${tier}" | bc)" ]; then
520 song_tier=$((song_tier+1))
521 fi
522 done
523 song_tier=$(printf "Tier%02d" $song_tier)
524
525 if [ "$song_faver" = "$me" ]; then
526 persons_folder="$faves_folder"
527 else
528 formatted_person="$(tr '[:lower:]' '[:upper:]' <<< ${song_faver:0:1})${song_faver:1}"
529 persons_folder=${external_favourite_naming_scheme/\%person\%/$formatted_person}
530 fi
531
532 song=$(echo ${hash_map[$song_hash]} | cut -sd / -f2)
533 song_dir="Songs/${persons_folder}/${song}/"
534 song_dir=$(echo $song_dir | sed 's/&/\&amp;/g; s/</\&lt;/g; s/>/\&gt;/g; s/"/\&quot;/g; s/'"'"'/\&apos;/g')
535 new_nodes="$new_nodes\n<Song Dir=\"$song_dir\" >\
536 \n<Steps Difficulty=\"$song_difficulty\" StepsType=\"$song_steps_type\" >\
537 \n<HighScoreList>\
538 \n<HighScore>\
539 \n<Name>$song_pranker</Name>\
540 \n<Grade>$song_tier</Grade>\
541 \n<PercentDP>$song_score</PercentDP>\
542 \n<Score>42069</Score>\
543 \n</HighScore>\
544 \n<LastPlayed>2019-03-10</LastPlayed>\
545 \n<NumTimesPlayed>1</NumTimesPlayed>\
546 \n</HighScoreList>\
547 \n</Steps>"
548
549 processed_pranks[$j]+="pranked"
550
551 echo "Song : $song_dir"
552 echo "Difficulty : $song_difficulty"
553 echo "Steps type : $song_steps_type"
554 echo "Pranker : $song_pranker"
555 echo "Score : $song_score"
556 echo "Tier : $song_tier"
557 echo -e "\n"
558
559 for d in "${difficulties[@]}"; do
560 for t in "${step_types[@]}"; do
561 # there are pranks for other difficulties of this chart
562 # we need to process them now because they need to live in the
563 # same song node
564 if ! [ -z "${pranks[${song_hash}:${d}:${t}]}" ]; then
565 if ! [ "$d" = "$song_difficulty" ] || ! [ "$t" = "$song_steps_type" ]; then
566 whatever="${pranks[${song_hash}:${d}:${t}]}"
567 ssong_pranker=$(echo $whatever | cut -sd : -f1)
568 ssong_score=$(echo $whatever | cut -sd : -f2)
569 ssong_tier=1
570 for tier in "${tiers[@]}"; do
571 if [ 1 -eq "$(echo "$ssong_score < ${tier}" | bc)" ]; then
572 ssong_tier=$((ssong_tier+1))
573 fi
574 done
575 ssong_tier=$(printf "Tier%02d" $ssong_tier)
576
577 processed_pranks["${song_hash}:${d}:${t}"]+="pranked"
578 new_nodes="$new_nodes\n<Steps Difficulty=\"${d}\" StepsType=\"${t}\" >\
579 \n<HighScoreList>\
580 \n<HighScore>\
581 \n<Name>$ssong_pranker</Name>\
582 \n<Grade>$ssong_tier</Grade>\
583 \n<PercentDP>$ssong_score</PercentDP>\
584 \n<Score>42069</Score>\
585 \n</HighScore>\
586 \n<LastPlayed>2019-03-10</LastPlayed>\
587 \n<NumTimesPlayed>1</NumTimesPlayed>\
588 \n</HighScoreList>\
589 \n</Steps>"
590
591 echo "Song : $song_dir"
592 echo "Difficulty : $d"
593 echo "Steps type : $t"
594 echo "Pranker : $ssong_pranker"
595 echo "Score : $ssong_score"
596 echo "Tier : $ssong_tier"
597 echo -e "\n"
598 fi
599 fi
600 done
601 done
602
603 new_nodes="$new_nodes\n</Song>"
604 fi
605 done
606
607 for nully in "${!null_files[@]}"; do
608 faver="${all_song_hashes[${nully}]}"
609
610 if [ "$faver" = "$me" ]; then
611 persons_folder="$faves_folder"
612 else
613 formatted_person="$(tr '[:lower:]' '[:upper:]' <<< ${faver:0:1})${faver:1}"
614 persons_folder=${external_favourite_naming_scheme/\%person\%/$formatted_person}
615 fi
616
617 path="$(echo ${hash_map[${nully}]} | cut -sd / -f2)"
618 path=$(echo $path | sed 's/&/\&amp;/g; s/</\&lt;/g; s/>/\&gt;/g; s/"/\&quot;/g; s/'"'"'/\&apos;/g')
619 song_path="Songs/${persons_folder}/${path}/"
620
621 empty_nodes="${empty_nodes}\n<Song Dir=\"$song_path\" >\
622 \n<Steps Difficulty=\"Challenge\" StepsType=\"dance-single\">\
623 \n<HighScoreList>\
624 \n<LastPlayed>1933-01-02</LastPlayed>\
625 \n<NumTimesPlayed>1</NumTimesPlayed>\
626 \n</HighScoreList>\
627 \n</Steps>\
628 \n</Song>"
629 done
630
631 # blow away all existing nodes in the favourites folders, we will make them ourselves and append to the end of the file
632 cmd="xmlstarlet ed -L ${xmlstarlet_deletes} \"${path_to_stats}\""
633 $(eval "$cmd")
634
635 last_tags_removed=$(head -n -2 "${path_to_stats}")
636 echo -e "${last_tags_removed}${new_nodes}\n${empty_nodes}\n</SongScores>\n</Stats>" > "${path_to_stats}"
637 fi
638
639 sed -i '1s/.*/<?xml version="1.0" encoding="UTF-8" ?>/' "${path_to_stats}"