danoniplus 27.5.1 → 27.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/js/danoni_main.js CHANGED
@@ -4,12 +4,12 @@
4
4
  *
5
5
  * Source by tickle
6
6
  * Created : 2018/10/08
7
- * Revised : 2022/05/22
7
+ * Revised : 2022/07/31
8
8
  *
9
9
  * https://github.com/cwtickle/danoniplus
10
10
  */
11
- const g_version = `Ver 27.5.1`;
12
- const g_revisedDate = `2022/05/22`;
11
+ const g_version = `Ver 27.8.0`;
12
+ const g_revisedDate = `2022/07/31`;
13
13
  const g_alphaVersion = ``;
14
14
 
15
15
  // カスタム用バージョン (danoni_custom.js 等で指定可)
@@ -43,8 +43,8 @@ const current = _ => {
43
43
  if (document.currentScript) {
44
44
  return document.currentScript.src;
45
45
  }
46
- const scripts = document.getElementsByTagName(`script`);
47
- const targetScript = scripts[scripts.length - 1];
46
+ const scripts = Array.from(document.getElementsByTagName(`script`));
47
+ const targetScript = scripts.find(file => file.src.endsWith(`danoni_main.js`));
48
48
  return targetScript.src;
49
49
  };
50
50
  const g_rootPath = current().match(/(^.*\/)/)[0];
@@ -465,8 +465,12 @@ const blockCode = _setCode => !C_BLOCK_KEYS.map(key => g_kCdN[key]).includes(_se
465
465
  * @param {object} _evt
466
466
  * @param {string} _displayName
467
467
  * @param {function} _func
468
+ * @param {boolean} _dfEvtFlg
468
469
  */
469
- const commonKeyDown = (_evt, _displayName, _func = _code => { }) => {
470
+ const commonKeyDown = (_evt, _displayName, _func = _code => { }, _dfEvtFlg) => {
471
+ if (!_dfEvtFlg) {
472
+ _evt.preventDefault();
473
+ }
470
474
  const setCode = transCode(_evt.code);
471
475
  if (_evt.repeat && (g_unrepeatObj.page.includes(_displayName) || g_unrepeatObj.key.includes(setCode))) {
472
476
  return blockCode(setCode);
@@ -542,12 +546,12 @@ const createScTextCommon = _displayName => {
542
546
  * @param {string} _displayName
543
547
  * @param {function} _func
544
548
  */
545
- const setShortcutEvent = (_displayName, _func = _ => true, _displayFlg = true) => {
546
- if (_displayFlg) {
549
+ const setShortcutEvent = (_displayName, _func = _ => true, { displayFlg = true, dfEvtFlg = false } = {}) => {
550
+ if (displayFlg) {
547
551
  createScTextCommon(_displayName);
548
552
  }
549
553
  const evList = _ => {
550
- document.onkeydown = evt => commonKeyDown(evt, _displayName, _func);
554
+ document.onkeydown = evt => commonKeyDown(evt, _displayName, _func, dfEvtFlg);
551
555
  document.onkeyup = evt => commonKeyUp(evt);
552
556
  };
553
557
  if (g_initialFlg && g_btnWaitFrame[_displayName].initial) {
@@ -1248,7 +1252,10 @@ const getTitleDivLabel = (_id, _titlename, _x, _y, ..._classes) =>
1248
1252
  */
1249
1253
  const resetKeyControl = _ => {
1250
1254
  document.onkeyup = _ => { };
1251
- document.onkeydown = evt => blockCode(transCode(evt.code));
1255
+ document.onkeydown = evt => {
1256
+ evt.preventDefault();
1257
+ return blockCode(transCode(evt.code));
1258
+ };
1252
1259
  g_inputKeyBuffer = {};
1253
1260
  };
1254
1261
 
@@ -3342,17 +3349,18 @@ const keysConvert = (_dosObj, { keyExtraList = _dosObj.keyExtraList.split(`,`) }
3342
3349
  const newKeyMultiParam = (_key, _name, _convFunc, { errCd = ``, baseCopyFlg = false, loopFunc = _ => true } = {}) => {
3343
3350
  let tmpMinPatterns = 1;
3344
3351
  const keyheader = _name + _key;
3352
+ const dfPtn = setIntVal(g_keyObj.dfPtnNum);
3345
3353
  if (hasVal(_dosObj[keyheader])) {
3346
3354
  const tmpArray = splitLF2(_dosObj[keyheader]);
3347
3355
  tmpMinPatterns = tmpArray.length;
3348
3356
  for (let k = 0; k < tmpMinPatterns; k++) {
3349
- if (existParam(tmpArray[k], `${keyheader}_${k}`)) {
3357
+ if (existParam(tmpArray[k], `${keyheader}_${k + dfPtn}`)) {
3350
3358
  continue;
3351
3359
  }
3352
- g_keyObj[`${keyheader}_${k}`] = g_keyObj[`${_name}${tmpArray[k]}`] !== undefined ?
3360
+ g_keyObj[`${keyheader}_${k + dfPtn}`] = g_keyObj[`${_name}${tmpArray[k]}`] !== undefined ?
3353
3361
  copyArray2d(g_keyObj[`${_name}${tmpArray[k]}`]) : tmpArray[k].split(`,`).map(n => _convFunc(n));
3354
3362
  if (baseCopyFlg) {
3355
- g_keyObj[`${keyheader}_${k}d`] = copyArray2d(g_keyObj[`${keyheader}_${k}`]);
3363
+ g_keyObj[`${keyheader}_${k + dfPtn}d`] = copyArray2d(g_keyObj[`${keyheader}_${k + dfPtn}`]);
3356
3364
  }
3357
3365
  loopFunc(k, keyheader);
3358
3366
  }
@@ -3370,10 +3378,11 @@ const keysConvert = (_dosObj, { keyExtraList = _dosObj.keyExtraList.split(`,`) }
3370
3378
  */
3371
3379
  const newKeySingleParam = (_key, _name, _type) => {
3372
3380
  const keyheader = _name + _key;
3381
+ const dfPtn = setIntVal(g_keyObj.dfPtnNum);
3373
3382
  if (_dosObj[keyheader] !== undefined) {
3374
3383
  const tmps = _dosObj[keyheader].split(`$`);
3375
3384
  for (let k = 0; k < tmps.length; k++) {
3376
- g_keyObj[`${keyheader}_${k}`] = setVal(g_keyObj[`${_name}${tmps[k]}`], setVal(tmps[k], ``, _type));
3385
+ g_keyObj[`${keyheader}_${k + dfPtn}`] = setVal(g_keyObj[`${_name}${tmps[k]}`], setVal(tmps[k], ``, _type));
3377
3386
  }
3378
3387
  }
3379
3388
  };
@@ -3388,11 +3397,12 @@ const keysConvert = (_dosObj, { keyExtraList = _dosObj.keyExtraList.split(`,`) }
3388
3397
  */
3389
3398
  const newKeyPairParam = (_key, _name, _pairName, _defaultName = ``, _defaultVal = 0) => {
3390
3399
  const keyheader = _name + _key;
3400
+ const dfPtn = setIntVal(g_keyObj.dfPtnNum);
3391
3401
 
3392
3402
  if (_dosObj[keyheader] !== undefined) {
3393
3403
  const tmpParams = splitLF2(_dosObj[keyheader]);
3394
3404
  for (let k = 0; k < tmpParams.length; k++) {
3395
- const pairName = `${_pairName}${_key}_${k}`;
3405
+ const pairName = `${_pairName}${_key}_${k + dfPtn}`;
3396
3406
  if (!hasVal(tmpParams[k])) {
3397
3407
  continue;
3398
3408
  }
@@ -3401,7 +3411,7 @@ const keysConvert = (_dosObj, { keyExtraList = _dosObj.keyExtraList.split(`,`) }
3401
3411
  Object.assign(g_keyObj[pairName], g_keyObj[`${_pairName}${tmpParams[k]}`]);
3402
3412
  } else {
3403
3413
  if (_defaultName !== ``) {
3404
- g_keyObj[pairName][_defaultName] = [...Array(g_keyObj[`color${_key}_${k}`].length)].fill(_defaultVal);
3414
+ g_keyObj[pairName][_defaultName] = [...Array(g_keyObj[`color${_key}_${k + dfPtn}`].length)].fill(_defaultVal);
3405
3415
  }
3406
3416
  tmpParams[k].split(`/`).forEach(pairs => {
3407
3417
  const tmpParamPair = pairs.split(`::`);
@@ -3418,18 +3428,31 @@ const keysConvert = (_dosObj, { keyExtraList = _dosObj.keyExtraList.split(`,`) }
3418
3428
  * @param {string} _header
3419
3429
  * @returns
3420
3430
  */
3421
- const copyChildArray = (_k, _header) => g_keyObj[`${_header}_${_k}_0`] = copyArray2d(g_keyObj[`${_header}_${_k}`]);
3431
+ const copyChildArray = (_k, _header) =>
3432
+ g_keyObj[`${_header}_${_k + g_keyObj.dfPtnNum}_0`] = copyArray2d(g_keyObj[`${_header}_${_k + g_keyObj.dfPtnNum}`]);
3422
3433
 
3423
3434
  // 対象キー毎に処理
3424
3435
  keyExtraList.forEach(newKey => {
3425
3436
  let tmpDivPtn = [];
3426
3437
  let tmpMinPatterns = 1;
3438
+ g_keyObj.dfPtnNum = 0;
3439
+
3440
+ // キーパターンの追記 (appendX)
3441
+ if (setBoolVal(_dosObj[`append${newKey}`])) {
3442
+ for (let j = 0; ; j++) {
3443
+ if (g_keyObj[`color${newKey}_${j}`] === undefined) {
3444
+ break;
3445
+ }
3446
+ g_keyObj.dfPtnNum++;
3447
+ }
3448
+ }
3449
+ const dfPtnNum = g_keyObj.dfPtnNum;
3427
3450
 
3428
3451
  // キーの名前 (keyNameX)
3429
3452
  g_keyObj[`keyName${newKey}`] = _dosObj[`keyName${newKey}`] ?? newKey;
3430
3453
 
3431
3454
  // キーの最小横幅 (minWidthX)
3432
- g_keyObj[`minWidth${newKey}`] = _dosObj[`minWidth${newKey}`] ?? g_keyObj.minWidthDefault;
3455
+ g_keyObj[`minWidth${newKey}`] = _dosObj[`minWidth${newKey}`] ?? g_keyObj[`minWidth${newKey}`] ?? g_keyObj.minWidthDefault;
3433
3456
 
3434
3457
  // 矢印色パターン (colorX_Y)
3435
3458
  tmpMinPatterns = newKeyMultiParam(newKey, `color`, toNumber, {
@@ -3451,24 +3474,25 @@ const keysConvert = (_dosObj, { keyExtraList = _dosObj.keyExtraList.split(`,`) }
3451
3474
  const tmpDivs = _dosObj[`div${newKey}`].split(`$`);
3452
3475
  for (let k = 0; k < tmpDivs.length; k++) {
3453
3476
  tmpDivPtn = tmpDivs[k].split(`,`);
3477
+ const ptnName = `${newKey}_${k + dfPtnNum}`;
3454
3478
 
3455
3479
  if (setIntVal(tmpDivPtn[0], -1) !== -1) {
3456
- g_keyObj[`div${newKey}_${k}`] = setIntVal(tmpDivPtn[0], g_keyObj[`chara${newKey}_0`].length);
3480
+ g_keyObj[`div${ptnName}`] = setIntVal(tmpDivPtn[0], g_keyObj[`chara${newKey}_0`].length);
3457
3481
  } else if (g_keyObj[`div${tmpDivPtn[0]}`] !== undefined) {
3458
3482
  // 既定キーパターンが指定された場合、存在すればその値を適用
3459
- g_keyObj[`div${newKey}_${k}`] = g_keyObj[`div${tmpDivPtn[0]}`];
3460
- g_keyObj[`divMax${newKey}_${k}`] = setIntVal(g_keyObj[`divMax${tmpDivPtn[0]}`], undefined);
3461
- } else if (setIntVal(g_keyObj[`div${newKey}_${k}`], -1) !== -1) {
3483
+ g_keyObj[`div${ptnName}`] = g_keyObj[`div${tmpDivPtn[0]}`];
3484
+ g_keyObj[`divMax${ptnName}`] = setIntVal(g_keyObj[`divMax${tmpDivPtn[0]}`], undefined);
3485
+ } else if (setIntVal(g_keyObj[`div${ptnName}`], -1) !== -1) {
3462
3486
  // すでに定義済みの場合はスキップ
3463
3487
  continue;
3464
3488
  } else if (g_keyObj[`chara${newKey}_0`] !== undefined) {
3465
3489
  // 特に指定が無い場合はcharaX_Yの配列長で決定
3466
- g_keyObj[`div${newKey}_${k}`] = g_keyObj[`chara${newKey}_0`].length;
3490
+ g_keyObj[`div${ptnName}`] = g_keyObj[`chara${newKey}_0`].length;
3467
3491
  }
3468
3492
 
3469
3493
  // ステップゾーン位置の最終番号
3470
3494
  if (tmpDivPtn.length > 1) {
3471
- g_keyObj[`divMax${newKey}_${k}`] = setVal(tmpDivPtn[1], -1, C_TYP_FLOAT);
3495
+ g_keyObj[`divMax${ptnName}`] = setVal(tmpDivPtn[1], -1, C_TYP_FLOAT);
3472
3496
  }
3473
3497
  }
3474
3498
  }
@@ -3476,16 +3500,18 @@ const keysConvert = (_dosObj, { keyExtraList = _dosObj.keyExtraList.split(`,`) }
3476
3500
  // ステップゾーン位置 (posX_Y)
3477
3501
  newKeyMultiParam(newKey, `pos`, toFloat, {
3478
3502
  loopFunc: (k, keyheader) => {
3479
- if (g_keyObj[`divMax${newKey}_${k}`] === undefined || g_keyObj[`divMax${newKey}_${k}`] === -1) {
3480
- const posLength = g_keyObj[`${keyheader}_${k}`].length;
3481
- g_keyObj[`divMax${newKey}_${k}`] = g_keyObj[`${keyheader}_${k}`][posLength - 1] + 1;
3503
+ const ptnName = `${newKey}_${k + dfPtnNum}`;
3504
+ if (g_keyObj[`divMax${ptnName}`] === undefined || g_keyObj[`divMax${ptnName}`] === -1) {
3505
+ const posLength = g_keyObj[`${keyheader}_${k + dfPtnNum}`].length;
3506
+ g_keyObj[`divMax${ptnName}`] = g_keyObj[`${keyheader}_${k + dfPtnNum}`][posLength - 1] + 1;
3482
3507
  }
3483
3508
  }
3484
3509
  });
3485
3510
  if (_dosObj[`pos${newKey}`] === undefined) {
3486
3511
  for (let k = 0; k < tmpMinPatterns; k++) {
3487
- if (g_keyObj[`color${newKey}_${k}`] !== undefined) {
3488
- g_keyObj[`pos${newKey}_${k}`] = [...Array(g_keyObj[`color${newKey}_${k}`].length).keys()].map(i => i);
3512
+ const ptnName = `${newKey}_${k + dfPtnNum}`;
3513
+ if (g_keyObj[`color${ptnName}`] !== undefined) {
3514
+ g_keyObj[`pos${ptnName}`] = [...Array(g_keyObj[`color${ptnName}`].length).keys()].map(i => i);
3489
3515
  }
3490
3516
  }
3491
3517
  }
@@ -3807,7 +3833,7 @@ const titleInit = _ => {
3807
3833
  g_timeoutEvtTitleId = setTimeout(_ => flowTitleTimeline(), 1000 / g_fps);
3808
3834
 
3809
3835
  // キー操作イベント(デフォルト)
3810
- setShortcutEvent(g_currentPage);
3836
+ setShortcutEvent(g_currentPage, _ => true, { dfEvtFlg: true });
3811
3837
 
3812
3838
  document.oncontextmenu = _ => true;
3813
3839
  divRoot.oncontextmenu = _ => false;
@@ -3972,7 +3998,7 @@ const optionInit = _ => {
3972
3998
  commonSettingBtn(`Display`);
3973
3999
 
3974
4000
  // キー操作イベント(デフォルト)
3975
- setShortcutEvent(g_currentPage);
4001
+ setShortcutEvent(g_currentPage, _ => true, { dfEvtFlg: true });
3976
4002
  document.oncontextmenu = _ => true;
3977
4003
  g_initialFlg = true;
3978
4004
 
@@ -4053,7 +4079,7 @@ const createOptionWindow = _sprite => {
4053
4079
  deleteChildspriteAll(`difList`);
4054
4080
  [`difList`, `difCover`, `btnDifU`, `btnDifD`].forEach(obj => optionsprite.removeChild(document.getElementById(obj)));
4055
4081
  g_currentPage = `option`;
4056
- setShortcutEvent(g_currentPage, _ => true, false);
4082
+ setShortcutEvent(g_currentPage, _ => true, { displayFlg: false, dfEvtFlg: true });
4057
4083
  }
4058
4084
  };
4059
4085
 
@@ -4233,45 +4259,55 @@ const createOptionWindow = _sprite => {
4233
4259
  if (g_headerObj.scoreDetailUse) {
4234
4260
  spriteList.speed.appendChild(
4235
4261
  createCss2Button(`btnGraph`, `i`, _ => true, {
4236
- x: 415, y: 0, w: 23, h: 23, siz: C_SIZ_JDGCNTS, title: g_msgObj.graph,
4262
+ x: -25, y: -60, w: 30, h: 30, siz: C_SIZ_JDGCHARA, title: g_msgObj.graph,
4237
4263
  resetFunc: _ => setScoreDetail(), cxtFunc: _ => setScoreDetail(),
4238
4264
  }, g_cssObj.button_Mini)
4239
4265
  );
4240
4266
  g_stateObj.scoreDetailViewFlg = false;
4241
4267
  const scoreDetail = createEmptySprite(optionsprite, `scoreDetail`, g_windowObj.scoreDetail, g_cssObj.settings_DifSelector);
4242
- const viewScText = _ => createScText(lnkScoreDetail, `ScoreDetail`, { targetLabel: `lnkScoreDetail`, x: -10 });
4243
4268
 
4244
4269
  /**
4245
4270
  * 譜面明細表示の切替
4246
4271
  * @param {number} _val
4247
4272
  */
4248
- const changeScoreDetail = (_val = 1) => {
4273
+ const changeScoreDetail = (_val = 0) => {
4274
+ if (g_currentPage === `difSelector`) {
4275
+ resetDifWindow();
4276
+ }
4249
4277
  g_stateObj.scoreDetailViewFlg = true;
4250
4278
  scoreDetail.style.visibility = `visible`;
4279
+
4280
+ // 表示内容を非表示化、ボタン色をデフォルトに戻す
4251
4281
  $id(`detail${g_stateObj.scoreDetail}`).visibility = `hidden`;
4252
- setSetting(_val, `scoreDetail`);
4253
- viewScText();
4282
+ document.getElementById(`lnk${g_stateObj.scoreDetail}G`).classList.replace(g_cssObj.button_Setting, g_cssObj.button_Default);
4283
+
4284
+ // 選択先を表示、ボタン色を選択中に変更
4285
+ g_stateObj.scoreDetail = g_settings.scoreDetails[_val];
4254
4286
  $id(`detail${g_stateObj.scoreDetail}`).visibility = `visible`;
4287
+ document.getElementById(`lnk${g_stateObj.scoreDetail}G`).classList.replace(g_cssObj.button_Default, g_cssObj.button_Setting);
4255
4288
  };
4256
4289
 
4257
4290
  multiAppend(scoreDetail,
4258
4291
  createScoreDetail(`Speed`),
4259
4292
  createScoreDetail(`Density`),
4260
4293
  createScoreDetail(`ToolDif`, false),
4261
- makeSettingLblCssButton(`lnkScoreDetailB`, `- - -`, 0, _ => changeScoreDetail(-1),
4262
- g_lblPosObj.lnkScoreDetailB, g_cssObj.button_RevON),
4263
- makeSettingLblCssButton(`lnkScoreDetail`, `${getStgDetailName(g_stateObj.scoreDetail)}`, 0, _ => changeScoreDetail(),
4264
- Object.assign(g_lblPosObj.lnkScoreDetail, {
4265
- cxtFunc: _ => changeScoreDetail(-1),
4266
- }), g_cssObj.button_RevON),
4267
4294
  );
4268
- viewScText();
4295
+ g_settings.scoreDetails.forEach((sd, j) => {
4296
+ scoreDetail.appendChild(
4297
+ makeDifLblCssButton(`lnk${sd}G`, getStgDetailName(sd), j, _ => changeScoreDetail(j), { w: C_LEN_DIFCOVER_WIDTH, btnStyle: (g_stateObj.scoreDetail === sd ? `Setting` : `Default`) })
4298
+ );
4299
+ createScText(document.getElementById(`lnk${sd}G`), sd, { targetLabel: `lnk${sd}G`, x: -10 });
4300
+ });
4269
4301
  }
4270
4302
 
4271
4303
  /**
4272
4304
  * 譜面明細表示/非表示ボタンの処理
4273
4305
  */
4274
4306
  const setScoreDetail = _ => {
4307
+ if (g_currentPage === `difSelector`) {
4308
+ resetDifWindow();
4309
+ g_stateObj.scoreDetailViewFlg = false;
4310
+ }
4275
4311
  const scoreDetail = document.querySelector(`#scoreDetail`);
4276
4312
  const detailObj = document.querySelector(`#detail${g_stateObj.scoreDetail}`);
4277
4313
  const visibles = [`hidden`, `visible`];
@@ -4413,7 +4449,7 @@ const createOptionWindow = _sprite => {
4413
4449
  const baseLabel = (_bLabel, _bLabelname, _bAlign) =>
4414
4450
  document.querySelector(`#detail${_name}`).appendChild(
4415
4451
  createDivCss2Label(`${_bLabel}`, `${_bLabelname}`, {
4416
- x: 10, y: 65 + _pos * 20, w: 100, h: 20, siz: C_SIZ_DIFSELECTOR, align: _bAlign,
4452
+ x: 10, y: 105 + _pos * 20, w: 100, h: 20, siz: C_SIZ_DIFSELECTOR, align: _bAlign,
4417
4453
  })
4418
4454
  );
4419
4455
  if (document.querySelector(`#data${_label}`) === null) {
@@ -4518,7 +4554,7 @@ const createOptionWindow = _sprite => {
4518
4554
  makeDifInfoLabel(`dataArrowInfo`, ``, g_lblPosObj.dataArrowInfo),
4519
4555
  makeDifInfoLabel(`lblArrowInfo2`, ``, g_lblPosObj.lblArrowInfo2),
4520
4556
  makeDifInfoLabel(`dataArrowInfo2`, ``, g_lblPosObj.dataArrowInfo2),
4521
- makeSettingLblCssButton(`lnkDifInfo`, g_lblNameObj.s_print, 0, _ => {
4557
+ makeDifLblCssButton(`lnkDifInfo`, g_lblNameObj.s_print, 8, _ => {
4522
4558
  copyTextToClipboard(
4523
4559
  `****** ${g_lblNameObj.s_printTitle} [${g_version}] ******\r\n\r\n`
4524
4560
  + `\t${g_lblNameObj.s_printHeader}\r\n\r\n${printData}`, g_msgInfoObj.I_0003
@@ -5,7 +5,7 @@
5
5
  *
6
6
  * Source by tickle
7
7
  * Created : 2019/11/19
8
- * Revised : 2022/05/21 (v27.5.0)
8
+ * Revised : 2022/07/31 (v27.8.0)
9
9
  *
10
10
  * https://github.com/cwtickle/danoniplus
11
11
  */
@@ -207,7 +207,7 @@ const updateWindowSiz = _ => {
207
207
  x: 140, y: 70, w: 275, h: 150, overflow: `auto`,
208
208
  },
209
209
  lnkDifInfo: {
210
- x: 10, y: 30, w: 100, borderStyle: `solid`,
210
+ w: C_LEN_DIFCOVER_WIDTH, borderStyle: `solid`,
211
211
  },
212
212
 
213
213
  /** ディスプレイ画面 */
@@ -624,9 +624,9 @@ let g_allFrz = 0;
624
624
  let g_fullArrows = 0;
625
625
  let g_currentArrows = 0;
626
626
  const g_rankObj = {
627
- rankMarks: [`SS`, `S`, `SA`, `AAA`, `AA`, `A`, `B`, `C`],
628
- rankRate: [97, 90, 85, 80, 75, 70, 50, 0],
629
- rankColor: [`#00ccff`, `#6600ff`, `#ff9900`, `#ff0000`, `#00ff00`, `#ff00ff`, `#cc00ff`, `#cc9933`],
627
+ rankMarks: [`SS`, `S`, `SA`, `AAA`, `AA`, `A`, `B`, `C`, `D`],
628
+ rankRate: [97, 90, 85, 80, 75, 70, 65, 60, 0],
629
+ rankColor: [`#00ccff`, `#6600ff`, `#ff9900`, `#ff0000`, `#00ff00`, `#ff00ff`, `#cc00ff`, `#cc9933`, `#33cc99`],
630
630
 
631
631
  rankMarkAllPerfect: `AP`,
632
632
  rankColorAllPerfect: ``,
@@ -1192,8 +1192,12 @@ const g_shortcutObj = {
1192
1192
  KeyV: { id: `lnkVolumeR` },
1193
1193
 
1194
1194
  KeyI: { id: `btnGraph` },
1195
- ShiftLeft_KeyQ: { id: `lnkScoreDetailB` },
1196
- KeyQ: { id: `lnkScoreDetail` },
1195
+ Digit1: { id: `lnkSpeedG` },
1196
+ Digit2: { id: `lnkDensityG` },
1197
+ Digit3: { id: `lnkToolDifG` },
1198
+ Numpad1: { id: `lnkSpeedG` },
1199
+ Numpad2: { id: `lnkDensityG` },
1200
+ Numpad3: { id: `lnkToolDifG` },
1197
1201
  KeyP: { id: `lnkDifInfo` },
1198
1202
  KeyZ: { id: `btnSave` },
1199
1203
 
@@ -1212,6 +1216,15 @@ const g_shortcutObj = {
1212
1216
  ArrowDown: { id: `btnDifD` },
1213
1217
  ArrowUp: { id: `btnDifU` },
1214
1218
 
1219
+ KeyI: { id: `btnGraph` },
1220
+ Digit1: { id: `lnkSpeedG` },
1221
+ Digit2: { id: `lnkDensityG` },
1222
+ Digit3: { id: `lnkToolDifG` },
1223
+ Numpad1: { id: `lnkSpeedG` },
1224
+ Numpad2: { id: `lnkDensityG` },
1225
+ Numpad3: { id: `lnkToolDifG` },
1226
+ KeyP: { id: `lnkDifInfo` },
1227
+
1215
1228
  Escape: { id: `btnBack` },
1216
1229
  Space: { id: `btnKeyConfig` },
1217
1230
  Enter: { id: `lnkDifficulty` },
@@ -1412,6 +1425,7 @@ const g_keyObj = {
1412
1425
  currentPtn: 0,
1413
1426
 
1414
1427
  prevKey: `Dummy`,
1428
+ dfPtnNum: 0,
1415
1429
 
1416
1430
  // キー別ヘッダー
1417
1431
  // - 譜面データ中に出てくる矢印(ノーツ)の種類と順番(ステップゾーン表示順)を管理する。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "danoniplus",
3
- "version": "27.5.1",
3
+ "version": "27.8.0",
4
4
  "description": "Dancing☆Onigiri (CW Edition) - Web-based Rhythm Game",
5
5
  "main": "index.js",
6
6
  "scripts": {