2018-10-11 06:13:24 +08:00
|
|
|
|
class ParseTja{
|
2019-11-04 22:20:44 +08:00
|
|
|
|
constructor(file, difficulty, stars, offset, metaOnly){
|
2018-10-11 06:13:24 +08:00
|
|
|
|
this.data = []
|
|
|
|
|
for(let line of file){
|
2020-03-12 12:59:28 +08:00
|
|
|
|
var indexComment = line.indexOf("//")
|
|
|
|
|
if(indexComment !== -1 && !line.trim().toLowerCase().startsWith("maker:")){
|
|
|
|
|
line = line.slice(0, indexComment).trim()
|
|
|
|
|
}else{
|
|
|
|
|
line = line.trim()
|
|
|
|
|
}
|
2018-10-11 06:13:24 +08:00
|
|
|
|
if(line !== ""){
|
|
|
|
|
this.data.push(line)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
this.difficulty = difficulty
|
2019-11-04 22:20:44 +08:00
|
|
|
|
this.stars = stars
|
2018-10-11 06:13:24 +08:00
|
|
|
|
this.offset = (offset || 0) * -1000
|
|
|
|
|
this.soundOffset = 0
|
2019-03-16 05:34:48 +08:00
|
|
|
|
this.noteTypes = {
|
|
|
|
|
"0": {name: false, txt: false},
|
|
|
|
|
"1": {name: "don", txt: strings.note.don},
|
|
|
|
|
"2": {name: "ka", txt: strings.note.ka},
|
|
|
|
|
"3": {name: "daiDon", txt: strings.note.daiDon},
|
|
|
|
|
"4": {name: "daiKa", txt: strings.note.daiKa},
|
|
|
|
|
"5": {name: "drumroll", txt: strings.note.drumroll},
|
|
|
|
|
"6": {name: "daiDrumroll", txt: strings.note.daiDrumroll},
|
|
|
|
|
"7": {name: "balloon", txt: strings.note.balloon},
|
|
|
|
|
"8": {name: false, txt: false},
|
|
|
|
|
"9": {name: "balloon", txt: strings.note.balloon},
|
|
|
|
|
"A": {name: "daiDon", txt: strings.note.daiDon},
|
|
|
|
|
"B": {name: "daiKa", txt: strings.note.daiKa}
|
|
|
|
|
}
|
2019-11-04 20:59:13 +08:00
|
|
|
|
this.noteTypes_ex = strings.ex_note;
|
2018-10-13 02:04:28 +08:00
|
|
|
|
this.courseTypes = {
|
|
|
|
|
"0": "easy",
|
|
|
|
|
"1": "normal",
|
|
|
|
|
"2": "hard",
|
|
|
|
|
"3": "oni",
|
|
|
|
|
"4": "ura",
|
|
|
|
|
"edit": "ura"
|
|
|
|
|
}
|
2018-10-11 06:13:24 +08:00
|
|
|
|
|
|
|
|
|
this.metadata = this.parseMetadata()
|
|
|
|
|
this.measures = []
|
|
|
|
|
this.beatInfo = {}
|
2020-03-15 23:00:23 +08:00
|
|
|
|
this.events = []
|
2018-12-06 04:33:34 +08:00
|
|
|
|
if(!metaOnly){
|
|
|
|
|
this.circles = this.parseCircles()
|
|
|
|
|
}
|
2018-10-11 06:13:24 +08:00
|
|
|
|
}
|
|
|
|
|
parseMetadata(){
|
2019-06-21 11:17:11 +08:00
|
|
|
|
var metaNumbers = ["bpm", "offset", "demostart", "level", "scoremode", "scorediff"]
|
2018-10-11 06:13:24 +08:00
|
|
|
|
var inSong = false
|
2019-01-05 15:44:28 +08:00
|
|
|
|
var hasSong = false
|
2018-10-11 06:13:24 +08:00
|
|
|
|
var courses = {}
|
|
|
|
|
var currentCourse = {}
|
2019-03-06 05:48:30 +08:00
|
|
|
|
var courseName = "oni"
|
2018-10-11 06:13:24 +08:00
|
|
|
|
for(var lineNum = 0; lineNum < this.data.length; lineNum++){
|
|
|
|
|
var line = this.data[lineNum]
|
|
|
|
|
|
|
|
|
|
if(line.slice(0, 1) === "#"){
|
|
|
|
|
|
|
|
|
|
var name = line.slice(1).toLowerCase()
|
|
|
|
|
if(name === "start" && !inSong){
|
|
|
|
|
|
|
|
|
|
inSong = true
|
2019-01-05 15:44:28 +08:00
|
|
|
|
if(!hasSong){
|
2019-03-06 05:48:30 +08:00
|
|
|
|
if(!(courseName in courses)){
|
|
|
|
|
courses[courseName] = {}
|
|
|
|
|
}
|
2019-01-05 15:44:28 +08:00
|
|
|
|
for(var name in currentCourse){
|
2019-02-18 00:26:46 +08:00
|
|
|
|
if(name !== "branch"){
|
|
|
|
|
courses[courseName][name] = currentCourse[name]
|
|
|
|
|
}
|
2018-10-11 06:13:24 +08:00
|
|
|
|
}
|
2019-01-05 15:44:28 +08:00
|
|
|
|
courses[courseName].start = lineNum + 1
|
|
|
|
|
courses[courseName].end = this.data.length
|
2018-10-11 06:13:24 +08:00
|
|
|
|
}
|
|
|
|
|
}else if(name === "end" && inSong){
|
|
|
|
|
inSong = false
|
2019-01-05 15:44:28 +08:00
|
|
|
|
if(!hasSong){
|
|
|
|
|
hasSong = true
|
|
|
|
|
courses[courseName].end = lineNum
|
|
|
|
|
}
|
2019-02-18 00:26:46 +08:00
|
|
|
|
}else if(name.startsWith("branchstart") && inSong){
|
|
|
|
|
courses[courseName].branch = true
|
2020-03-31 20:50:27 +08:00
|
|
|
|
}else if(name.startsWith("lyric") && inSong){
|
|
|
|
|
courses[courseName].inlineLyrics = true
|
2018-10-11 06:13:24 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}else if(!inSong){
|
|
|
|
|
|
|
|
|
|
if(line.indexOf(":") > 0){
|
|
|
|
|
|
|
|
|
|
var [name, value] = this.split(line, ":")
|
|
|
|
|
name = name.toLowerCase().trim()
|
|
|
|
|
value = value.trim()
|
|
|
|
|
|
|
|
|
|
if(name === "course"){
|
2018-10-13 02:04:28 +08:00
|
|
|
|
value = value.toLowerCase()
|
2018-10-11 06:13:24 +08:00
|
|
|
|
if(value in this.courseTypes){
|
|
|
|
|
courseName = this.courseTypes[value]
|
|
|
|
|
}else{
|
2018-10-13 02:04:28 +08:00
|
|
|
|
courseName = value
|
2018-10-11 06:13:24 +08:00
|
|
|
|
}
|
2019-01-05 15:44:28 +08:00
|
|
|
|
hasSong = false
|
2018-10-11 06:13:24 +08:00
|
|
|
|
}else if(name === "balloon"){
|
|
|
|
|
value = value ? value.split(",").map(digit => parseInt(digit)) : []
|
|
|
|
|
}else if(this.inArray(name, metaNumbers)){
|
|
|
|
|
value = parseFloat(value)
|
|
|
|
|
}
|
2019-06-21 11:17:11 +08:00
|
|
|
|
else if (name === "scoreinit") {
|
|
|
|
|
value = value ? parseFloat(value.split(",")[0]) : 0;
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-11 06:13:24 +08:00
|
|
|
|
currentCourse[name] = value
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return courses
|
|
|
|
|
}
|
|
|
|
|
inArray(string, array){
|
|
|
|
|
return array.indexOf(string) >= 0
|
|
|
|
|
}
|
|
|
|
|
split(string, delimiter){
|
|
|
|
|
var index = string.indexOf(delimiter)
|
|
|
|
|
if(index < 0){
|
|
|
|
|
return [string, ""]
|
|
|
|
|
}
|
|
|
|
|
return [string.slice(0, index), string.slice(index + delimiter.length)]
|
|
|
|
|
}
|
|
|
|
|
parseCircles(){
|
2019-11-28 14:04:40 +08:00
|
|
|
|
var meta = this.metadata[this.difficulty] || {}
|
2018-10-11 06:13:24 +08:00
|
|
|
|
var ms = (meta.offset || 0) * -1000 + this.offset
|
2019-03-06 05:48:30 +08:00
|
|
|
|
var bpm = Math.abs(meta.bpm) || 120
|
2018-10-11 06:13:24 +08:00
|
|
|
|
var scroll = 1
|
|
|
|
|
var measure = 4
|
|
|
|
|
this.beatInfo.beatInterval = 60000 / bpm
|
|
|
|
|
var gogo = false
|
|
|
|
|
var barLine = true
|
|
|
|
|
|
|
|
|
|
var balloonID = 0
|
|
|
|
|
var balloons = meta.balloon || []
|
|
|
|
|
|
|
|
|
|
var lastDrumroll = false
|
2019-02-18 00:26:46 +08:00
|
|
|
|
|
2018-10-11 06:13:24 +08:00
|
|
|
|
var branch = false
|
2019-02-18 00:26:46 +08:00
|
|
|
|
var branchObj = {}
|
|
|
|
|
var currentBranch = false
|
|
|
|
|
var branchSettings = {}
|
2019-02-21 04:48:21 +08:00
|
|
|
|
var branchFirstMeasure = false
|
2019-02-18 00:26:46 +08:00
|
|
|
|
var sectionBegin = true
|
2020-03-12 12:59:28 +08:00
|
|
|
|
var lastBpm = bpm
|
|
|
|
|
var lastGogo = gogo
|
2020-04-17 09:53:53 +08:00
|
|
|
|
var lyricsLine = null
|
2018-10-11 06:13:24 +08:00
|
|
|
|
|
|
|
|
|
var currentMeasure = []
|
|
|
|
|
var firstNote = true
|
|
|
|
|
var circles = []
|
|
|
|
|
var circleID = 0
|
2019-03-16 05:34:48 +08:00
|
|
|
|
var regexAZ = /[A-Z]/
|
2020-03-09 20:36:57 +08:00
|
|
|
|
var regexSpace = /\s/
|
2020-03-31 21:44:54 +08:00
|
|
|
|
var regexLinebreak = /\\n/g
|
2019-11-04 20:59:13 +08:00
|
|
|
|
var isAllDon = (note_chain, start_pos) => {
|
|
|
|
|
for (var i = start_pos; i < note_chain.length; ++i) {
|
|
|
|
|
var note = note_chain[i];
|
|
|
|
|
if (note && note.type !== "don" && note.type !== "daiDon") {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
var checkChain = (note_chain, measure_length, is_last) => {
|
|
|
|
|
//console.log(note_chain, measure_length, is_last);
|
|
|
|
|
/*if (measure_length >= 24) {
|
|
|
|
|
for (var note of note_chain) {
|
|
|
|
|
note.text = this.noteTypes_ex[note.type][0];
|
|
|
|
|
}
|
|
|
|
|
} else { */
|
|
|
|
|
var alldon_pos = null;
|
|
|
|
|
for (var i = 0; i < note_chain.length - (is_last ? 1 : 0); ++i) {
|
|
|
|
|
var note = note_chain[i];
|
|
|
|
|
if (alldon_pos === null && is_last && isAllDon(note_chain, i)) {
|
|
|
|
|
alldon_pos = i;
|
|
|
|
|
}
|
|
|
|
|
note.text = this.noteTypes_ex[note.type][alldon_pos != null ? (i - alldon_pos) % 2 : 0];
|
|
|
|
|
}
|
|
|
|
|
//}
|
|
|
|
|
}
|
2018-10-11 06:13:24 +08:00
|
|
|
|
var pushMeasure = () => {
|
2019-02-18 00:26:46 +08:00
|
|
|
|
var note = currentMeasure[0]
|
|
|
|
|
if(note){
|
|
|
|
|
var speed = note.bpm * note.scroll / 60
|
|
|
|
|
}else{
|
|
|
|
|
var speed = bpm * scroll / 60
|
2018-10-11 06:13:24 +08:00
|
|
|
|
}
|
2019-02-18 00:26:46 +08:00
|
|
|
|
this.measures.push({
|
|
|
|
|
ms: ms,
|
|
|
|
|
originalMS: ms,
|
|
|
|
|
speed: speed,
|
|
|
|
|
visible: barLine,
|
2019-02-21 04:48:21 +08:00
|
|
|
|
branch: currentBranch,
|
|
|
|
|
branchFirst: branchFirstMeasure
|
2019-02-18 00:26:46 +08:00
|
|
|
|
})
|
2019-02-21 04:48:21 +08:00
|
|
|
|
branchFirstMeasure = false
|
2018-10-11 07:41:02 +08:00
|
|
|
|
if(currentMeasure.length){
|
|
|
|
|
for(var i = 0; i < currentMeasure.length; i++){
|
|
|
|
|
var note = currentMeasure[i]
|
2020-03-12 12:59:28 +08:00
|
|
|
|
if(firstNote && note.type && note.type !== "event"){
|
2018-10-11 07:41:02 +08:00
|
|
|
|
firstNote = false
|
|
|
|
|
if(ms < 0){
|
|
|
|
|
this.soundOffset = ms
|
|
|
|
|
ms = 0
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
note.start = ms
|
|
|
|
|
if(note.endDrumroll){
|
|
|
|
|
note.endDrumroll.endTime = ms
|
2018-10-15 04:33:22 +08:00
|
|
|
|
note.endDrumroll.originalEndTime = ms
|
2018-10-11 07:41:02 +08:00
|
|
|
|
}
|
2018-10-12 00:15:28 +08:00
|
|
|
|
var msPerMeasure = 60000 * measure / note.bpm
|
2018-10-11 07:41:02 +08:00
|
|
|
|
ms += msPerMeasure / currentMeasure.length
|
|
|
|
|
}
|
2019-11-04 20:59:13 +08:00
|
|
|
|
var note_chain = [];
|
|
|
|
|
for (var i = 0; i < currentMeasure.length; i++){
|
|
|
|
|
//console.log(note_chain.length);
|
2018-10-11 07:41:02 +08:00
|
|
|
|
var note = currentMeasure[i]
|
2019-11-04 20:59:13 +08:00
|
|
|
|
if (note.type) {
|
2018-10-11 07:41:02 +08:00
|
|
|
|
circleID++
|
|
|
|
|
var circleObj = new Circle({
|
|
|
|
|
id: circleID,
|
|
|
|
|
start: note.start,
|
|
|
|
|
type: note.type,
|
|
|
|
|
txt: note.txt,
|
|
|
|
|
speed: note.bpm * note.scroll / 60,
|
|
|
|
|
gogoTime: note.gogo,
|
|
|
|
|
endTime: note.endTime,
|
2018-10-12 04:24:18 +08:00
|
|
|
|
requiredHits: note.requiredHits,
|
2019-02-18 00:26:46 +08:00
|
|
|
|
beatMS: 60000 / note.bpm,
|
|
|
|
|
branch: currentBranch,
|
|
|
|
|
section: note.section
|
2018-10-11 07:41:02 +08:00
|
|
|
|
})
|
2019-11-04 20:59:13 +08:00
|
|
|
|
if (note.type === "don" || note.type === "ka" || note.type === "daiDon" || note.type === "daiKa") {
|
|
|
|
|
note_chain.push(circleObj);
|
|
|
|
|
} else {
|
|
|
|
|
if (note_chain.length > 1 && currentMeasure.length >= 8) {
|
|
|
|
|
checkChain(note_chain, currentMeasure.length, false);
|
|
|
|
|
}
|
|
|
|
|
note_chain = [];
|
|
|
|
|
}
|
|
|
|
|
if (lastDrumroll === note) {
|
2018-10-11 07:41:02 +08:00
|
|
|
|
lastDrumroll = circleObj
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-15 23:00:23 +08:00
|
|
|
|
if(note.event){
|
|
|
|
|
this.events.push(circleObj)
|
|
|
|
|
}
|
|
|
|
|
if(note.type !== "event"){
|
|
|
|
|
circles.push(circleObj)
|
|
|
|
|
}
|
2019-11-04 20:59:13 +08:00
|
|
|
|
} else if (!(currentMeasure.length >= 24 && (!currentMeasure[i + 1] || currentMeasure[i + 1].type))
|
|
|
|
|
&& !(currentMeasure.length >= 48 && (!currentMeasure[i + 2] || currentMeasure[i + 2].type || !currentMeasure[i + 3] || currentMeasure[i + 3].type))) {
|
|
|
|
|
if (note_chain.length > 1 && currentMeasure.length >= 8) {
|
|
|
|
|
checkChain(note_chain, currentMeasure.length, true);
|
|
|
|
|
}
|
|
|
|
|
note_chain = [];
|
2018-10-11 07:41:02 +08:00
|
|
|
|
}
|
2020-04-17 09:53:53 +08:00
|
|
|
|
if("lyricsLine" in note){
|
|
|
|
|
if(!this.lyrics){
|
|
|
|
|
this.lyrics = []
|
|
|
|
|
}
|
|
|
|
|
if(this.lyrics.length !== 0){
|
|
|
|
|
this.lyrics[this.lyrics.length - 1].end = note.start
|
|
|
|
|
}
|
|
|
|
|
this.lyrics.push({
|
|
|
|
|
start: note.start,
|
|
|
|
|
text: note.lyricsLine
|
|
|
|
|
})
|
|
|
|
|
}
|
2018-10-11 07:41:02 +08:00
|
|
|
|
}
|
2019-11-04 20:59:13 +08:00
|
|
|
|
if (note_chain.length > 1 && currentMeasure.length >= 8) {
|
|
|
|
|
checkChain(note_chain, currentMeasure.length, false);
|
|
|
|
|
}
|
2018-10-11 07:41:02 +08:00
|
|
|
|
}else{
|
|
|
|
|
var msPerMeasure = 60000 * measure / bpm
|
|
|
|
|
ms += msPerMeasure
|
|
|
|
|
}
|
2018-10-11 06:13:24 +08:00
|
|
|
|
}
|
2020-03-12 12:59:28 +08:00
|
|
|
|
var insertNote = circleObj => {
|
|
|
|
|
if(circleObj){
|
2020-03-15 23:00:23 +08:00
|
|
|
|
if(bpm !== lastBpm || gogo !== lastGogo){
|
|
|
|
|
circleObj.event = true
|
|
|
|
|
lastBpm = bpm
|
|
|
|
|
lastGogo = gogo
|
|
|
|
|
}
|
2020-04-17 09:53:53 +08:00
|
|
|
|
if(lyricsLine !== null){
|
|
|
|
|
circleObj.lyricsLine = lyricsLine
|
|
|
|
|
lyricsLine = null
|
|
|
|
|
}
|
2020-03-12 12:59:28 +08:00
|
|
|
|
currentMeasure.push(circleObj)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
var insertBlankNote = circleObj => {
|
|
|
|
|
if(bpm !== lastBpm || gogo !== lastGogo){
|
|
|
|
|
insertNote({
|
|
|
|
|
type: "event",
|
|
|
|
|
bpm: bpm,
|
|
|
|
|
scroll: scroll,
|
|
|
|
|
gogo: gogo
|
|
|
|
|
})
|
|
|
|
|
}else if(!circleObj){
|
2020-04-17 09:53:53 +08:00
|
|
|
|
var circleObj2 = {
|
2020-03-12 12:59:28 +08:00
|
|
|
|
bpm: bpm,
|
|
|
|
|
scroll: scroll
|
2020-04-17 09:53:53 +08:00
|
|
|
|
}
|
|
|
|
|
if(lyricsLine !== null){
|
|
|
|
|
circleObj2.lyricsLine = lyricsLine
|
|
|
|
|
lyricsLine = null
|
|
|
|
|
}
|
|
|
|
|
currentMeasure.push(circleObj2)
|
2020-03-12 12:59:28 +08:00
|
|
|
|
}
|
|
|
|
|
if(circleObj){
|
2020-04-17 09:53:53 +08:00
|
|
|
|
if(lyricsLine !== null){
|
|
|
|
|
circleObj.lyricsLine = lyricsLine
|
|
|
|
|
lyricsLine = null
|
|
|
|
|
}
|
2020-03-12 12:59:28 +08:00
|
|
|
|
currentMeasure.push(circleObj)
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-10-11 06:13:24 +08:00
|
|
|
|
|
|
|
|
|
for(var lineNum = meta.start; lineNum < meta.end; lineNum++){
|
|
|
|
|
var line = this.data[lineNum]
|
|
|
|
|
if(line.slice(0, 1) === "#"){
|
|
|
|
|
|
2020-04-17 09:53:53 +08:00
|
|
|
|
var line = line.slice(1)
|
2018-10-11 06:13:24 +08:00
|
|
|
|
var [name, value] = this.split(line, " ")
|
2020-04-17 09:53:53 +08:00
|
|
|
|
name = name.toLowerCase()
|
2018-10-11 06:13:24 +08:00
|
|
|
|
|
|
|
|
|
switch(name){
|
2019-02-18 00:26:46 +08:00
|
|
|
|
case "gogostart":
|
|
|
|
|
gogo = true
|
|
|
|
|
break
|
|
|
|
|
case "gogoend":
|
|
|
|
|
gogo = false
|
|
|
|
|
break
|
|
|
|
|
case "bpmchange":
|
2019-02-21 04:48:21 +08:00
|
|
|
|
bpm = parseFloat(value) || bpm
|
2019-02-18 00:26:46 +08:00
|
|
|
|
break
|
|
|
|
|
case "scroll":
|
2019-03-06 05:48:30 +08:00
|
|
|
|
scroll = Math.abs(parseFloat(value)) || scroll
|
2019-02-18 00:26:46 +08:00
|
|
|
|
break
|
|
|
|
|
case "measure":
|
|
|
|
|
var [numerator, denominator] = value.split("/")
|
2019-02-21 04:48:21 +08:00
|
|
|
|
measure = numerator / denominator * 4 || measure
|
2019-02-18 00:26:46 +08:00
|
|
|
|
break
|
|
|
|
|
case "delay":
|
|
|
|
|
ms += (parseFloat(value) || 0) * 1000
|
|
|
|
|
break
|
|
|
|
|
case "barlineon":
|
|
|
|
|
barLine = true
|
|
|
|
|
break
|
|
|
|
|
case "barlineoff":
|
|
|
|
|
barLine = false
|
|
|
|
|
break
|
2018-10-11 06:13:24 +08:00
|
|
|
|
case "branchstart":
|
|
|
|
|
branch = true
|
2019-02-18 00:26:46 +08:00
|
|
|
|
currentBranch = false
|
2019-02-21 04:48:21 +08:00
|
|
|
|
branchFirstMeasure = true
|
2019-02-18 00:26:46 +08:00
|
|
|
|
branchSettings = {
|
|
|
|
|
ms: ms,
|
|
|
|
|
gogo: gogo,
|
|
|
|
|
bpm: bpm,
|
|
|
|
|
scroll: scroll,
|
|
|
|
|
sectionBegin: sectionBegin
|
|
|
|
|
}
|
2018-10-11 06:13:24 +08:00
|
|
|
|
value = value.split(",")
|
2019-02-18 00:26:46 +08:00
|
|
|
|
if(!this.branches){
|
|
|
|
|
this.branches = []
|
|
|
|
|
}
|
2019-02-21 04:48:21 +08:00
|
|
|
|
var req = {
|
|
|
|
|
advanced: parseFloat(value[1]) || 0,
|
|
|
|
|
master: parseFloat(value[2]) || 0
|
|
|
|
|
}
|
|
|
|
|
if(req.advanced > 0){
|
|
|
|
|
var active = req.master > 0 ? "normal" : "master"
|
|
|
|
|
}else{
|
|
|
|
|
var active = req.master > 0 ? "advanced" : "master"
|
|
|
|
|
}
|
2019-02-18 00:26:46 +08:00
|
|
|
|
branchObj = {
|
|
|
|
|
ms: ms,
|
|
|
|
|
originalMS: ms,
|
2019-02-21 04:48:21 +08:00
|
|
|
|
active: active,
|
|
|
|
|
type: value[0].trim().toLowerCase() === "r" ? "drumroll" : "accuracy",
|
|
|
|
|
requirement: req
|
|
|
|
|
}
|
|
|
|
|
this.branches.push(branchObj)
|
|
|
|
|
if(this.measures.length === 1 && branchObj.type === "drumroll"){
|
|
|
|
|
for(var i = circles.length; i--;){
|
|
|
|
|
var circle = circles[i]
|
|
|
|
|
if(circle.endTime && circle.type === "drumroll" || circle.type === "daiDrumroll" || circle.type === "balloon"){
|
|
|
|
|
this.measures.push({
|
|
|
|
|
ms: circle.endTime,
|
|
|
|
|
originalMS: circle.endTime,
|
|
|
|
|
speed: circle.bpm * circle.scroll / 60,
|
|
|
|
|
visible: false,
|
|
|
|
|
branch: circle.branch
|
|
|
|
|
})
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if(this.measures.length !== 0){
|
|
|
|
|
this.measures[this.measures.length - 1].nextBranch = branchObj
|
2018-10-11 06:13:24 +08:00
|
|
|
|
}
|
|
|
|
|
break
|
|
|
|
|
case "branchend":
|
|
|
|
|
branch = false
|
2019-02-18 00:26:46 +08:00
|
|
|
|
currentBranch = false
|
|
|
|
|
break
|
|
|
|
|
case "section":
|
|
|
|
|
sectionBegin = true
|
|
|
|
|
if(branch && !currentBranch){
|
|
|
|
|
branchSettings.sectionBegin = true
|
|
|
|
|
}
|
2018-10-11 06:13:24 +08:00
|
|
|
|
break
|
|
|
|
|
case "n": case "e": case "m":
|
2019-02-21 04:48:21 +08:00
|
|
|
|
if(!branch){
|
|
|
|
|
break
|
2019-02-18 00:26:46 +08:00
|
|
|
|
}
|
|
|
|
|
ms = branchSettings.ms
|
|
|
|
|
gogo = branchSettings.gogo
|
|
|
|
|
bpm = branchSettings.bpm
|
|
|
|
|
scroll = branchSettings.scroll
|
|
|
|
|
sectionBegin = branchSettings.sectionBegin
|
2019-02-21 04:48:21 +08:00
|
|
|
|
branchFirstMeasure = true
|
2019-02-18 00:26:46 +08:00
|
|
|
|
var branchName = name === "m" ? "master" : (name === "e" ? "advanced" : "normal")
|
|
|
|
|
currentBranch = {
|
|
|
|
|
name: branchName,
|
2019-02-21 04:48:21 +08:00
|
|
|
|
active: branchName === branchObj.active
|
2019-02-18 00:26:46 +08:00
|
|
|
|
}
|
|
|
|
|
branchObj[branchName] = currentBranch
|
2018-10-11 06:13:24 +08:00
|
|
|
|
break
|
2020-03-31 20:50:27 +08:00
|
|
|
|
case "lyric":
|
2020-04-17 09:53:53 +08:00
|
|
|
|
lyricsLine = value.replace(regexLinebreak, "\n").trim()
|
2020-03-31 20:50:27 +08:00
|
|
|
|
break
|
2018-10-11 06:13:24 +08:00
|
|
|
|
}
|
|
|
|
|
|
2019-02-18 00:26:46 +08:00
|
|
|
|
}else{
|
2018-10-11 06:13:24 +08:00
|
|
|
|
|
2019-03-16 05:34:48 +08:00
|
|
|
|
var string = line.toUpperCase().split("")
|
2018-10-11 06:13:24 +08:00
|
|
|
|
|
|
|
|
|
for(let symbol of string){
|
|
|
|
|
|
|
|
|
|
var error = false
|
|
|
|
|
switch(symbol){
|
|
|
|
|
|
|
|
|
|
case "0":
|
2020-03-12 12:59:28 +08:00
|
|
|
|
insertBlankNote()
|
2018-10-11 06:13:24 +08:00
|
|
|
|
break
|
2019-03-16 05:34:48 +08:00
|
|
|
|
case "1": case "2": case "3": case "4": case "A": case "B":
|
2018-10-11 06:13:24 +08:00
|
|
|
|
var type = this.noteTypes[symbol]
|
|
|
|
|
var circleObj = {
|
|
|
|
|
type: type.name,
|
|
|
|
|
txt: type.txt,
|
|
|
|
|
gogo: gogo,
|
|
|
|
|
bpm: bpm,
|
2019-02-18 00:26:46 +08:00
|
|
|
|
scroll: scroll,
|
|
|
|
|
section: sectionBegin
|
2018-10-11 06:13:24 +08:00
|
|
|
|
}
|
2019-02-18 00:26:46 +08:00
|
|
|
|
sectionBegin = false
|
2018-10-11 06:13:24 +08:00
|
|
|
|
if(lastDrumroll){
|
|
|
|
|
circleObj.endDrumroll = lastDrumroll
|
|
|
|
|
lastDrumroll = false
|
|
|
|
|
}
|
2020-03-12 12:59:28 +08:00
|
|
|
|
insertNote(circleObj)
|
2018-10-11 06:13:24 +08:00
|
|
|
|
break
|
|
|
|
|
case "5": case "6": case "7": case "9":
|
|
|
|
|
var type = this.noteTypes[symbol]
|
|
|
|
|
var circleObj = {
|
|
|
|
|
type: type.name,
|
|
|
|
|
txt: type.txt,
|
|
|
|
|
gogo: gogo,
|
|
|
|
|
bpm: bpm,
|
2019-02-18 00:26:46 +08:00
|
|
|
|
scroll: scroll,
|
|
|
|
|
section: sectionBegin
|
2018-10-11 06:13:24 +08:00
|
|
|
|
}
|
2019-02-18 00:26:46 +08:00
|
|
|
|
sectionBegin = false
|
2018-10-11 06:13:24 +08:00
|
|
|
|
if(lastDrumroll){
|
2018-10-28 02:35:04 +08:00
|
|
|
|
if(symbol === "9"){
|
2020-03-12 12:59:28 +08:00
|
|
|
|
insertBlankNote({
|
2018-10-28 02:35:04 +08:00
|
|
|
|
endDrumroll: lastDrumroll,
|
|
|
|
|
bpm: bpm,
|
2019-02-18 00:26:46 +08:00
|
|
|
|
scroll: scroll,
|
|
|
|
|
section: sectionBegin
|
2018-10-28 02:35:04 +08:00
|
|
|
|
})
|
2019-02-18 00:26:46 +08:00
|
|
|
|
sectionBegin = false
|
2018-10-28 02:35:04 +08:00
|
|
|
|
lastDrumroll = false
|
2018-12-13 17:18:52 +08:00
|
|
|
|
}else{
|
2020-03-12 12:59:28 +08:00
|
|
|
|
insertBlankNote()
|
2018-10-28 02:35:04 +08:00
|
|
|
|
}
|
2018-12-13 17:18:52 +08:00
|
|
|
|
break
|
2018-10-11 06:13:24 +08:00
|
|
|
|
}
|
|
|
|
|
if(symbol === "7" || symbol === "9"){
|
|
|
|
|
var hits = balloons[balloonID]
|
|
|
|
|
if(!hits || hits < 1){
|
|
|
|
|
hits = 1
|
|
|
|
|
}
|
|
|
|
|
circleObj.requiredHits = hits
|
|
|
|
|
balloonID++
|
|
|
|
|
}
|
|
|
|
|
lastDrumroll = circleObj
|
2020-03-12 12:59:28 +08:00
|
|
|
|
insertNote(circleObj)
|
2018-10-11 06:13:24 +08:00
|
|
|
|
break
|
|
|
|
|
case "8":
|
|
|
|
|
if(lastDrumroll){
|
2020-03-12 12:59:28 +08:00
|
|
|
|
insertBlankNote({
|
2018-10-11 06:13:24 +08:00
|
|
|
|
endDrumroll: lastDrumroll,
|
|
|
|
|
bpm: bpm,
|
2019-02-18 00:26:46 +08:00
|
|
|
|
scroll: scroll,
|
|
|
|
|
section: sectionBegin
|
2018-10-11 06:13:24 +08:00
|
|
|
|
})
|
2019-02-18 00:26:46 +08:00
|
|
|
|
sectionBegin = false
|
2018-10-11 06:13:24 +08:00
|
|
|
|
lastDrumroll = false
|
|
|
|
|
}else{
|
2020-03-12 12:59:28 +08:00
|
|
|
|
insertBlankNote({
|
2018-10-11 06:13:24 +08:00
|
|
|
|
bpm: bpm,
|
|
|
|
|
scroll: scroll
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
break
|
|
|
|
|
case ",":
|
2020-04-17 09:53:53 +08:00
|
|
|
|
if(currentMeasure.length === 0 && (bpm !== lastBpm || gogo !== lastGogo || lyricsLine !== null)){
|
|
|
|
|
insertBlankNote()
|
2020-03-12 12:59:28 +08:00
|
|
|
|
}
|
2018-10-11 06:13:24 +08:00
|
|
|
|
pushMeasure()
|
|
|
|
|
currentMeasure = []
|
|
|
|
|
break
|
|
|
|
|
default:
|
2019-03-16 05:34:48 +08:00
|
|
|
|
if(regexAZ.test(symbol)){
|
2020-03-12 12:59:28 +08:00
|
|
|
|
insertBlankNote()
|
2020-03-09 20:36:57 +08:00
|
|
|
|
}else if(!regexSpace.test(symbol)){
|
2019-03-16 05:34:48 +08:00
|
|
|
|
error = true
|
|
|
|
|
}
|
2018-10-11 06:13:24 +08:00
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
if(error){
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
pushMeasure()
|
|
|
|
|
if(lastDrumroll){
|
|
|
|
|
lastDrumroll.endTime = ms
|
2018-10-15 04:33:22 +08:00
|
|
|
|
lastDrumroll.originalEndTime = ms
|
2018-10-11 06:13:24 +08:00
|
|
|
|
}
|
|
|
|
|
|
2019-02-18 00:26:46 +08:00
|
|
|
|
if(this.branches){
|
|
|
|
|
circles.sort((a, b) => a.ms > b.ms ? 1 : -1)
|
2019-02-21 04:48:21 +08:00
|
|
|
|
this.measures.sort((a, b) => a.ms > b.ms ? 1 : -1)
|
2019-02-18 00:26:46 +08:00
|
|
|
|
circles.forEach((circle, i) => circle.id = i + 1)
|
|
|
|
|
}
|
2019-11-01 00:10:53 +08:00
|
|
|
|
this.scoreinit = meta.scoreinit;
|
|
|
|
|
this.scorediff = meta.scorediff;
|
|
|
|
|
if (this.scoreinit && this.scorediff) {
|
|
|
|
|
this.scoremode = meta.scoremode || 1;
|
|
|
|
|
} else {
|
|
|
|
|
this.scoremode = meta.scoremode || 2;
|
2019-11-04 22:20:44 +08:00
|
|
|
|
var autoscore = new AutoScore(this.difficulty, this.stars, this.scoremode, circles);
|
2019-11-01 00:10:53 +08:00
|
|
|
|
this.scoreinit = autoscore.ScoreInit;
|
|
|
|
|
this.scorediff = autoscore.ScoreDiff;
|
|
|
|
|
}
|
2020-03-31 20:50:27 +08:00
|
|
|
|
if(this.lyrics){
|
|
|
|
|
var line = this.lyrics[this.lyrics.length - 1]
|
|
|
|
|
line.end = Math.max(ms, line.start) + 5000
|
|
|
|
|
}
|
2018-10-11 06:13:24 +08:00
|
|
|
|
return circles
|
|
|
|
|
}
|
|
|
|
|
}
|