5 use Services\ISimfileParser
;
8 class SimfileParser
implements ISimfileParser
11 private $_smFileLines;
13 public function parse($simfileData)
15 $this->_smFileLines
= explode(";", $simfileData);
18 public function banner()
20 return $this->extractKey('BANNER') ?
: null
;
23 public function title()
25 $title = $this->extractKey('TITLE');
26 if(!$title) throw new Exception ('Invalid SM file. TITLE missing');
28 //XXX: UTF8 encode to deal with unusual character that crop up in weeaboo shit.
29 return utf8_encode($title);
32 public function artist()
34 $artist = $this->extractKey('ARTIST');
35 if(!$artist) throw new Exception ('Invalid SM file. ARTIST missing');
37 //XXX: UTF8 encode to deal with unusual character that crop up in weeaboo shit.
38 return new \Domain\VOs\StepMania\
Artist(utf8_encode($artist));
41 public function stops()
43 $stops = $this->extractKey('STOPS');
45 //XXX: SM files can be missing stops.
46 //if($stops === false) throw new Exception ('Invalid SM file. STOPS missing');
51 public function fgChanges()
53 $fgChanges = $this->extractKey('FGCHANGES');
54 //XXX: Looks like fgChanges is allowed to be missing.
55 //if($fgChanges === false) throw new Exception ('Invalid SM file. FGCHANGES missing');
57 return (bool
)$fgChanges;
62 $displayBpm = $this->extractKey('DISPLAYBPM');
66 $bpmRange = explode(":",$displayBpm);
67 $bpmRange[1] = @$bpmRange[1] ?
: $bpmRange[0];
70 //XXX: Originally I had an else statement for this. But turns out some SM's have * as the display bpm
71 //so I just check if we don't have a displayBPM OR the displayBPM is not numeric.
72 if(!$displayBpm ||
!is_numeric($bpmRange[0]))
74 $bpms = $this->extractKey('BPMS');
75 $bpmRange = $this->parseBpms($bpms);
78 //XXX: I have nfi why I made the BPM VO high-low instead of low-high in the constructor but yolo
79 return new \Domain\VOs\StepMania\
BPM($bpmRange[1], $bpmRange[0]);
82 public function bgChanges()
84 $bgChanges = $this->extractKey('BGCHANGES');
86 //XXX: BGChanges can be missing
87 //if($bgChanges === false) throw new Exception ('Invalid SM file. BGCHANGES missing');
89 return (bool
)$bgChanges;
92 public function bpmChanges()
94 $bpms = $this->extractKey('BPMS');
96 //XXX: BPMS can be missing.
97 //if(!$bpms) throw new Exception ('Invalid SM file. BPMS missing');
99 $bpmRange = $this->parseBpms($bpms);
100 //XXX: We have bpm changes when the high and low bpms are different.
101 return $bpmRange[0] != $bpmRange[1];
104 public function subtitle()
106 $subtitle = $this->extractKey('SUBTITLE');
107 if(!$subtitle) throw new Exception ('Invalid SM file. SUBTITLE missing');
114 if(empty($this->_smFileLines
)) throw new Exception('SM file data not set.');
117 foreach ($this->_smFileLines
as $line)
119 $pos = strpos($line, '#NOTES:');
122 $noteData = trim(substr($line, $pos +
9));
123 $steps = $this->stepchartFromNoteData($noteData);
125 //XXX: Sometimes we get a cabinet lights chart, those return false for getGame.
126 //We don't want to store cabinet lights, so just ignore it.
127 if($steps->getMode()->getGame()) $allSteps[] = $steps;
131 if(empty($allSteps)) throw new Exception('Invalid Sm file. NOTES missing');
135 private function stepchartFromNoteData($noteData)
137 $stepData = array_map('trim', explode(':', $noteData));
138 return new \Domain\VOs\StepMania\
StepChart(
139 new \Domain\VOs\StepMania\
DanceMode($stepData[0]),
140 new \Domain\VOs\StepMania\
Difficulty($stepData[2]),
141 empty($stepData[1]) ? null
: new \Domain\VOs\StepMania\
StepArtist($stepData[1]),
146 private function extractKey($key)
148 if(empty($this->_smFileLines
)) throw new Exception('SM file data not set.');
150 foreach ($this->_smFileLines
as $line)
152 $pos = strpos($line, '#' . $key . ':');
153 if ($pos !== false
) return trim(substr($line, $pos +
strlen($key) +
2));
159 private function parseBpms($bpms)
161 $bpms = explode(",", $bpms);
162 $bpmRange = array('high' => null
, 'low' => null
);
164 foreach($bpms as $bpm)
166 $bpmMeasure = explode('=', $bpm);
167 $bpmValue = floatval($bpmMeasure[1]);
169 if(empty($bpmRange['low'])) $bpmRange['low'] = $bpmRange['high'] = $bpmValue;
171 $bpmRange['high'] = ($bpmValue > $bpmRange['high']) ?
$bpmValue : $bpmRange['high'];
172 $bpmRange['low'] = ($bpmValue < $bpmRange['low']) ?
$bpmValue : $bpmRange['low'];
175 return array($bpmRange['low'], $bpmRange['high']);