procon_bypass_man-web 0.1.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.
- checksums.yaml +7 -0
- data/.babelrc +6 -0
- data/.circleci/config.yml +73 -0
- data/.gitignore +12 -0
- data/.rspec +1 -0
- data/.rubocop.yml +26 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +18 -0
- data/Gemfile.lock +97 -0
- data/LICENSE.txt +21 -0
- data/Procfile +2 -0
- data/README.md +43 -0
- data/Rakefile +4 -0
- data/bin/console +15 -0
- data/bin/pbm_web +7 -0
- data/bin/setup +8 -0
- data/jest.config.ts +194 -0
- data/lib/procon_bypass_man/web.rb +20 -0
- data/lib/procon_bypass_man/web/db.rb +33 -0
- data/lib/procon_bypass_man/web/migration/001_create_settings_table.sql +4 -0
- data/lib/procon_bypass_man/web/models/base_model.rb +47 -0
- data/lib/procon_bypass_man/web/models/setting.rb +22 -0
- data/lib/procon_bypass_man/web/public/bundle.js +2 -0
- data/lib/procon_bypass_man/web/public/bundle.js.LICENSE.txt +57 -0
- data/lib/procon_bypass_man/web/public/index.html +1 -0
- data/lib/procon_bypass_man/web/server.rb +139 -0
- data/lib/procon_bypass_man/web/setting_parser.rb +190 -0
- data/lib/procon_bypass_man/web/storage.rb +25 -0
- data/lib/procon_bypass_man/web/version.rb +7 -0
- data/package.json +48 -0
- data/procon_bypass_man-web.gemspec +36 -0
- data/src/app.tsx +5 -0
- data/src/components/button_setting.tsx +142 -0
- data/src/components/buttons_modal.tsx +110 -0
- data/src/components/buttons_setting.tsx +67 -0
- data/src/components/installable_macros.tsx +58 -0
- data/src/components/installable_modes.tsx +57 -0
- data/src/components/macro_settings.tsx +85 -0
- data/src/components/mode_settings.tsx +62 -0
- data/src/contexts/buttons_setting.ts +2 -0
- data/src/index.html +11 -0
- data/src/lib/button_state.test.ts +110 -0
- data/src/lib/button_state.ts +52 -0
- data/src/lib/button_state_diff.test.ts +123 -0
- data/src/lib/button_state_diff.ts +63 -0
- data/src/lib/buttons_setting_converter.test.ts +185 -0
- data/src/lib/buttons_setting_converter.ts +107 -0
- data/src/lib/http_client.ts +93 -0
- data/src/pages/bpm_page.tsx +92 -0
- data/src/pages/buttons_setting_page.tsx +281 -0
- data/src/pages/global_setting_page.tsx +83 -0
- data/src/pages/home.tsx +17 -0
- data/src/pages/recoding_mode_page.tsx +15 -0
- data/src/pages/top.tsx +107 -0
- data/src/reducers/layer_reducer.ts +120 -0
- data/src/types/button.ts +2 -0
- data/src/types/buttons_setting_type.ts +63 -0
- data/src/types/layer_key.ts +2 -0
- data/src/types/pbm_stats.ts +1 -0
- data/src/types/plugin.ts +43 -0
- data/tmp/.keep +0 -0
- data/tsconfig.json +75 -0
- data/webpack.config.js +56 -0
- data/yarn.lock +6815 -0
- metadata +150 -0
@@ -0,0 +1,83 @@
|
|
1
|
+
/** @jsx jsx */
|
2
|
+
|
3
|
+
import { jsx, css } from '@emotion/react'
|
4
|
+
import React, { useState, useEffect } from "react";
|
5
|
+
import axios from 'axios';
|
6
|
+
|
7
|
+
import { HttpClient } from "../lib/http_client";
|
8
|
+
|
9
|
+
type Prop = {
|
10
|
+
};
|
11
|
+
const httpClient = new HttpClient();
|
12
|
+
|
13
|
+
export const GlobalSetting = ({}:Prop) => {
|
14
|
+
const [dirPath, setDirPath] = useState("");
|
15
|
+
const [settingPath, setSettingPath] = useState("");
|
16
|
+
const [serverResponseMessage, setServerResponseMessage] = useState("");
|
17
|
+
|
18
|
+
const inputStyle = css`
|
19
|
+
width: 400px;
|
20
|
+
`
|
21
|
+
|
22
|
+
useEffect(() => {
|
23
|
+
httpClient.getDirPath()
|
24
|
+
.then(function (response) {
|
25
|
+
setDirPath(response.data.root_path);
|
26
|
+
})
|
27
|
+
.catch(function (error) {
|
28
|
+
setServerResponseMessage("サーバとの通信に失敗しました");
|
29
|
+
console.log(error);
|
30
|
+
})
|
31
|
+
httpClient.getSettingPath()
|
32
|
+
.then(function (response) {
|
33
|
+
setSettingPath(response.data.setting_path);
|
34
|
+
})
|
35
|
+
.catch(function (error) {
|
36
|
+
console.log(error);
|
37
|
+
})
|
38
|
+
}, [])
|
39
|
+
|
40
|
+
const handleDirChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
41
|
+
setDirPath(e.target.value);
|
42
|
+
};
|
43
|
+
|
44
|
+
const handleDirSubmit = (e: React.MouseEvent<HTMLElement, MouseEvent>) => {
|
45
|
+
if (!(e.target instanceof HTMLInputElement)) {
|
46
|
+
return;
|
47
|
+
}
|
48
|
+
httpClient.postDirPath(dirPath);
|
49
|
+
setServerResponseMessage("PBMのディレクトリパスの更新に成功しました");
|
50
|
+
};
|
51
|
+
|
52
|
+
const handleSettingChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
53
|
+
setSettingPath(e.target.value);
|
54
|
+
};
|
55
|
+
|
56
|
+
const handleSettingSubmit = (e: React.MouseEvent<HTMLElement, MouseEvent>) => {
|
57
|
+
if (!(e.target instanceof HTMLInputElement)) {
|
58
|
+
return;
|
59
|
+
}
|
60
|
+
httpClient.postSettingPath(settingPath);
|
61
|
+
setServerResponseMessage("PBMの設定ファイルパスの更新に成功しました");
|
62
|
+
};
|
63
|
+
|
64
|
+
return (
|
65
|
+
<>
|
66
|
+
<h2>設定</h2>
|
67
|
+
<div>
|
68
|
+
{serverResponseMessage}
|
69
|
+
</div>
|
70
|
+
<label>PBMのディレクトリパス:
|
71
|
+
<input type="text" css={inputStyle} value={dirPath} onChange={handleDirChange} />
|
72
|
+
</label>
|
73
|
+
<input type="submit" value="更新する" onClick={handleDirSubmit} />
|
74
|
+
<hr />
|
75
|
+
|
76
|
+
<label>PBMの設定ファイルパス:
|
77
|
+
<input type="text" css={inputStyle} value={settingPath || "未設定"} onChange={handleSettingChange} />
|
78
|
+
</label>
|
79
|
+
<input type="submit" value="更新する" onClick={handleSettingSubmit} />
|
80
|
+
<hr />
|
81
|
+
</>
|
82
|
+
)
|
83
|
+
}
|
data/src/pages/home.tsx
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
/** @jsx jsx */
|
2
|
+
|
3
|
+
import { jsx, css } from '@emotion/react'
|
4
|
+
import React, { useState, useEffect } from "react";
|
5
|
+
|
6
|
+
export const Home = () => {
|
7
|
+
return (
|
8
|
+
<>
|
9
|
+
<div css={css`margin-top: 30px`}>
|
10
|
+
ソースコード: <a href="https://github.com/splaplapla/procon_bypass_man-web">
|
11
|
+
https://github.com/splaplapla/procon_bypass_man-web
|
12
|
+
</a>
|
13
|
+
</div>
|
14
|
+
</>
|
15
|
+
)
|
16
|
+
}
|
17
|
+
|
@@ -0,0 +1,15 @@
|
|
1
|
+
/** @jsx jsx */
|
2
|
+
|
3
|
+
import { jsx, css } from '@emotion/react'
|
4
|
+
import React, { useState, useEffect } from "react";
|
5
|
+
import { HttpClient } from "../lib/http_client";
|
6
|
+
|
7
|
+
const httpClient = new HttpClient();
|
8
|
+
|
9
|
+
export const RecodingModePage = () => {
|
10
|
+
return (
|
11
|
+
<>
|
12
|
+
<div></div>
|
13
|
+
</>
|
14
|
+
)
|
15
|
+
}
|
data/src/pages/top.tsx
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
/** @jsx jsx */
|
2
|
+
|
3
|
+
import { jsx, css } from '@emotion/react'
|
4
|
+
import React, { useState, useReducer } from "react";
|
5
|
+
import {
|
6
|
+
BrowserRouter as Router,
|
7
|
+
Switch,
|
8
|
+
Route,
|
9
|
+
Link
|
10
|
+
} from "react-router-dom";
|
11
|
+
import { GlobalSetting } from "./global_setting_page";
|
12
|
+
import { BpmPage } from "./bpm_page";
|
13
|
+
import { Home } from "./home";
|
14
|
+
import { ButtonsSettingPage } from "./buttons_setting_page";
|
15
|
+
import { RecodingModePage } from "./recoding_mode_page";
|
16
|
+
import { ButtonsSettingContext } from "./../contexts/buttons_setting";
|
17
|
+
import { ButtonsInLayer, Layers, ButtonsSettingType } from "../types/buttons_setting_type";
|
18
|
+
import { buttons, Button } from "../types/button";
|
19
|
+
import { LayerReducer } from "../reducers/layer_reducer";
|
20
|
+
|
21
|
+
const ButtonsSettingProfile: React.FC = ({children}) => {
|
22
|
+
const initLayers: Layers = {
|
23
|
+
up: buttons.reduce((a, i) => { a[i] = { open: false }; return a }, {} as ButtonsInLayer),
|
24
|
+
right: buttons.reduce((a, i) => { a[i] = { open: false }; return a }, {} as ButtonsInLayer),
|
25
|
+
down: buttons.reduce((a, i) => { a[i] = { open: false }; return a }, {} as ButtonsInLayer),
|
26
|
+
left: buttons.reduce((a, i) => { a[i] = { open: false }; return a }, {} as ButtonsInLayer),
|
27
|
+
installed_macros: {},
|
28
|
+
installed_modes: {},
|
29
|
+
}
|
30
|
+
const [prefixKeys, setPrefixKeys] = useState([]);
|
31
|
+
const [loaded, setLoaded] = useState(false);
|
32
|
+
const [layers, layersDispatch] = useReducer(LayerReducer, initLayers as Layers);
|
33
|
+
const value = {
|
34
|
+
loaded,
|
35
|
+
setLoaded,
|
36
|
+
layers,
|
37
|
+
prefixKeys,
|
38
|
+
setPrefixKeys,
|
39
|
+
layersDispatch,
|
40
|
+
}
|
41
|
+
return (
|
42
|
+
<ButtonsSettingContext.Provider value={value}>
|
43
|
+
{children}
|
44
|
+
</ButtonsSettingContext.Provider>
|
45
|
+
)
|
46
|
+
}
|
47
|
+
|
48
|
+
export const Top: React.FC = () => {
|
49
|
+
const menuStyle = css`
|
50
|
+
ul {
|
51
|
+
list-style: none;
|
52
|
+
display:flex;
|
53
|
+
margin: 0;
|
54
|
+
padding: 0;
|
55
|
+
li {
|
56
|
+
padding-right: 3px;
|
57
|
+
display: block;
|
58
|
+
a {
|
59
|
+
text-decoration: none;
|
60
|
+
display:block;
|
61
|
+
padding:10px;
|
62
|
+
background-color: #333;
|
63
|
+
color: white;
|
64
|
+
}
|
65
|
+
}
|
66
|
+
}
|
67
|
+
`;
|
68
|
+
|
69
|
+
return (
|
70
|
+
<>
|
71
|
+
<Router>
|
72
|
+
<div>
|
73
|
+
<nav css={menuStyle}>
|
74
|
+
<ul>
|
75
|
+
<li>
|
76
|
+
<Link to="/">home</Link>
|
77
|
+
</li>
|
78
|
+
<li>
|
79
|
+
<Link to="/setting">設定</Link>
|
80
|
+
</li>
|
81
|
+
<li>
|
82
|
+
<Link to="/buttons_setting">ボタン設定</Link>
|
83
|
+
</li>
|
84
|
+
</ul>
|
85
|
+
</nav>
|
86
|
+
<Switch>
|
87
|
+
<Route exact path="/" >
|
88
|
+
<Home />
|
89
|
+
</Route>
|
90
|
+
<Route path="/setting">
|
91
|
+
<GlobalSetting />
|
92
|
+
</Route>
|
93
|
+
<Route path="/pbm">
|
94
|
+
<BpmPage />
|
95
|
+
</Route>
|
96
|
+
<Route path="/buttons_setting">
|
97
|
+
<ButtonsSettingProfile><ButtonsSettingPage /></ButtonsSettingProfile>
|
98
|
+
</Route>
|
99
|
+
<Route path="/recoding_mode">
|
100
|
+
<RecodingModePage />
|
101
|
+
</Route>
|
102
|
+
</Switch>
|
103
|
+
</div>
|
104
|
+
</Router>
|
105
|
+
</>
|
106
|
+
);
|
107
|
+
};
|
@@ -0,0 +1,120 @@
|
|
1
|
+
import { buttons, Button } from "../types/button";
|
2
|
+
import { LayerKey } from "../types/layer_key";
|
3
|
+
import { Layers, Flip, Remap, Macro, StructMacro, ModeTable, StructMode } from "../types/buttons_setting_type";
|
4
|
+
|
5
|
+
export const disableFlipType = Symbol('disableFlip');
|
6
|
+
export const alwaysFlipType = Symbol('alwaysFlip');
|
7
|
+
export const flipIfPressedSelfType = Symbol('flipIfPressedSelf');
|
8
|
+
export const flipIfPressedSomeButtonsType = Symbol('flipIfPressedSomeButtons');
|
9
|
+
export const ignoreButtonsInFlipingType = Symbol('ignoreButtonsInFliping');
|
10
|
+
export const remapType = Symbol('remap');
|
11
|
+
export const openMenuType = Symbol('openMenu');
|
12
|
+
export const closeMenuType = Symbol('closeMenu');
|
13
|
+
export const applyMacroType = Symbol('applyMacro');
|
14
|
+
export const installMacroType = Symbol('installedMacro');
|
15
|
+
export const uninstallMacroType = Symbol('uninstalledMacro');
|
16
|
+
export const installModeType = Symbol('uninstalledMacro');
|
17
|
+
export const uninstallModeType = Symbol('a')
|
18
|
+
export const applyModeType = Symbol('b')
|
19
|
+
|
20
|
+
|
21
|
+
type ACTION_TYPE =
|
22
|
+
| { type: typeof disableFlipType, payload: { layerKey: LayerKey, button: Button } }
|
23
|
+
| { type: typeof alwaysFlipType, payload: { layerKey: LayerKey, button: Button } }
|
24
|
+
| { type: typeof flipIfPressedSelfType, payload: { layerKey: LayerKey, button: Button } }
|
25
|
+
| { type: typeof flipIfPressedSomeButtonsType, payload: { layerKey: LayerKey, button: Button, targetButtons: Array<Button> } }
|
26
|
+
| { type: typeof ignoreButtonsInFlipingType, payload: { layerKey: LayerKey, button: Button, targetButtons: Array<Button> } }
|
27
|
+
| { type: typeof remapType, payload: { layerKey: LayerKey, button: Button, targetButtons: Array<Button> } }
|
28
|
+
| { type: typeof openMenuType, payload: { layerKey: LayerKey, button: Button } }
|
29
|
+
| { type: typeof closeMenuType, payload: { layerKey: LayerKey, button: Button } }
|
30
|
+
| { type: typeof applyMacroType, payload: { layerKey: LayerKey, button: (Button | undefined), macro: StructMacro } }
|
31
|
+
| { type: typeof installMacroType, payload: { layerKey: (LayerKey | undefined), button: (Button | undefined), installed_macro: string } }
|
32
|
+
| { type: typeof uninstallMacroType, payload: { layerKey: (LayerKey | undefined), button: (Button | undefined), installed_macro: string } }
|
33
|
+
| { type: typeof installModeType, payload: { layerKey: (LayerKey | undefined), button: (Button | undefined), installed_mode: string } }
|
34
|
+
| { type: typeof uninstallModeType, payload: { layerKey: (LayerKey | undefined), button: (Button | undefined), installed_mode: string } }
|
35
|
+
| { type: typeof applyModeType, payload: { layerKey: LayerKey, button: (Button | undefined), mode: StructMode } }
|
36
|
+
|
37
|
+
export const LayerReducer = (layers: Layers, action: ACTION_TYPE) => {
|
38
|
+
const layerKey = action.payload.layerKey as LayerKey;
|
39
|
+
const button = action.payload.button as Button;
|
40
|
+
|
41
|
+
const flip = layerKey && button && layers[layerKey][button]?.flip || {} as Flip
|
42
|
+
const remap = layerKey && button && layers[layerKey][button]?.remap || {} as Remap
|
43
|
+
|
44
|
+
switch (action.type) {
|
45
|
+
case disableFlipType:
|
46
|
+
flip.enable = false;
|
47
|
+
layers[layerKey][button] = { flip: flip, open: true }
|
48
|
+
return { ...layers };
|
49
|
+
case alwaysFlipType:
|
50
|
+
flip.if_pressed = [];
|
51
|
+
flip.enable = true;
|
52
|
+
layers[layerKey][button] = { flip: flip, open: true }
|
53
|
+
return { ...layers };
|
54
|
+
case flipIfPressedSelfType:
|
55
|
+
flip.if_pressed = [button];
|
56
|
+
flip.enable = true;
|
57
|
+
layers[layerKey][button] = { flip: flip, open: true }
|
58
|
+
return { ...layers };
|
59
|
+
case flipIfPressedSomeButtonsType:
|
60
|
+
flip.if_pressed = action.payload.targetButtons;
|
61
|
+
flip.enable = true;
|
62
|
+
layers[layerKey][button] = { flip: flip, open: true }
|
63
|
+
return { ...layers };
|
64
|
+
case ignoreButtonsInFlipingType:
|
65
|
+
flip.force_neutral = action.payload.targetButtons;
|
66
|
+
layers[layerKey][button] = { flip: flip, open: true }
|
67
|
+
return { ...layers };
|
68
|
+
case remapType:
|
69
|
+
flip.enable = false;
|
70
|
+
remap.to = action.payload.targetButtons;
|
71
|
+
layers[layerKey][button] = { flip: flip, remap: remap, open: true }
|
72
|
+
return { ...layers };
|
73
|
+
case openMenuType:
|
74
|
+
flip.enable = false;
|
75
|
+
layers[layerKey][button] = { flip: flip, open: true };
|
76
|
+
return { ...layers };
|
77
|
+
case closeMenuType:
|
78
|
+
flip.enable = false;
|
79
|
+
layers[layerKey][button] = { flip: flip, open: false }
|
80
|
+
return { ...layers };
|
81
|
+
case applyMacroType:
|
82
|
+
const structMacro = action.payload.macro
|
83
|
+
if(!structMacro) { return { ...layers } };
|
84
|
+
const macroTable = layers[layerKey].macro as Macro || {} as Macro
|
85
|
+
macroTable[structMacro.name] = structMacro.if_pressed.sort()
|
86
|
+
layers[layerKey].macro = macroTable
|
87
|
+
return { ...layers };
|
88
|
+
case installMacroType:
|
89
|
+
const installedMacro = action.payload.installed_macro
|
90
|
+
const h = { ...layers }
|
91
|
+
h.installed_macros ||= {}
|
92
|
+
h.installed_macros[installedMacro] = true
|
93
|
+
return h;
|
94
|
+
case uninstallMacroType:
|
95
|
+
const unregisterInstalledMacro = action.payload.installed_macro
|
96
|
+
const hh = { ...layers }
|
97
|
+
hh.installed_macros ||= {}
|
98
|
+
hh.installed_macros[unregisterInstalledMacro] = false
|
99
|
+
return hh;
|
100
|
+
case installModeType:
|
101
|
+
const installedMode = action.payload.installed_mode
|
102
|
+
const l = { ...layers }
|
103
|
+
l.installed_modes ||= {}
|
104
|
+
l.installed_modes[installedMode] = true
|
105
|
+
return l;
|
106
|
+
case uninstallModeType:
|
107
|
+
const uninstallMode = action.payload.installed_mode
|
108
|
+
const uml = { ...layers }
|
109
|
+
uml.installed_modes ||= {}
|
110
|
+
uml.installed_modes[uninstallMode] = false
|
111
|
+
return uml;
|
112
|
+
case applyModeType:
|
113
|
+
const applyMode = action.payload.mode;
|
114
|
+
layers[layerKey].mode = { [applyMode.name]: true};
|
115
|
+
return { ...layers };
|
116
|
+
default:
|
117
|
+
console.log("一致しないaction typeです")
|
118
|
+
return { ...layers };
|
119
|
+
}
|
120
|
+
};
|
data/src/types/button.ts
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
import { Button } from "./button";
|
2
|
+
import { LayerKey } from "./layer_key";
|
3
|
+
|
4
|
+
export type Flip = {
|
5
|
+
if_pressed?: Array<Button>,
|
6
|
+
enable: Boolean,
|
7
|
+
force_neutral?: Array<Button>,
|
8
|
+
}
|
9
|
+
|
10
|
+
export type StructMacro = {
|
11
|
+
name: string,
|
12
|
+
if_pressed: Array<Button>,
|
13
|
+
}
|
14
|
+
|
15
|
+
export type StructMode = {
|
16
|
+
name: string,
|
17
|
+
}
|
18
|
+
|
19
|
+
export type Macro = {
|
20
|
+
[key in string]: Array<Button>;
|
21
|
+
}
|
22
|
+
|
23
|
+
export type ModeTable = {
|
24
|
+
[key in string]: boolean;
|
25
|
+
}
|
26
|
+
|
27
|
+
export type Remap = {
|
28
|
+
to: Array<Button>,
|
29
|
+
}
|
30
|
+
|
31
|
+
export type ButtonInLayer = {
|
32
|
+
flip?: Flip,
|
33
|
+
macro?: Macro, // deprecated
|
34
|
+
remap?: Remap,
|
35
|
+
open: boolean,
|
36
|
+
}
|
37
|
+
|
38
|
+
type _ButtonsInLayer = {
|
39
|
+
[key in Button] : ButtonInLayer;
|
40
|
+
}
|
41
|
+
|
42
|
+
export type ButtonsInLayer = _ButtonsInLayer & {
|
43
|
+
macro?: Macro; // TODO macroTableという名前にしたい
|
44
|
+
mode?: ModeTable;
|
45
|
+
};
|
46
|
+
|
47
|
+
export type InstalledPlugin = {
|
48
|
+
[key in string]: boolean;
|
49
|
+
}
|
50
|
+
|
51
|
+
export type Layers = {
|
52
|
+
up: ButtonsInLayer,
|
53
|
+
right: ButtonsInLayer,
|
54
|
+
down: ButtonsInLayer,
|
55
|
+
left: ButtonsInLayer,
|
56
|
+
installed_macros?: InstalledPlugin,
|
57
|
+
installed_modes?: InstalledPlugin,
|
58
|
+
}
|
59
|
+
|
60
|
+
export type ButtonsSettingType = {
|
61
|
+
prefix_keys_for_changing_layer: Array<Button>;
|
62
|
+
layers: Layers;
|
63
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
export type PbmStats = "stopped" | "running" | "unknown" | "waiting" | "error";
|
data/src/types/plugin.ts
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
export type PluginBody = {
|
2
|
+
display_name: string;
|
3
|
+
class_namespace: string;
|
4
|
+
}
|
5
|
+
|
6
|
+
export type Plugin = {
|
7
|
+
[key in string] : {
|
8
|
+
modes: Array<PluginBody>;
|
9
|
+
macros: Array<PluginBody>;
|
10
|
+
}
|
11
|
+
}
|
12
|
+
|
13
|
+
// plugins.
|
14
|
+
export const AvailablePlugins = [
|
15
|
+
{
|
16
|
+
splatoon2: {
|
17
|
+
modes: [
|
18
|
+
{ display_name: "splatoon2.guruguru", class_namespace: "ProconBypassMan::Splatoon2::Mode::Guruguru" },
|
19
|
+
],
|
20
|
+
macros: [
|
21
|
+
{ display_name: "splatoon2.fast_return", class_namespace: "ProconBypassMan::Splatoon2::Macro::FastReturn" },
|
22
|
+
],
|
23
|
+
}
|
24
|
+
} as Plugin,
|
25
|
+
]
|
26
|
+
|
27
|
+
export const MacroNameMap = AvailablePlugins.reduce((hash, item: Plugin) => {
|
28
|
+
for (var [name, plugin] of Object.entries(item)) {
|
29
|
+
plugin.macros.forEach((macro: PluginBody) => {
|
30
|
+
hash[macro.class_namespace] = macro.display_name
|
31
|
+
})
|
32
|
+
};
|
33
|
+
return hash;
|
34
|
+
}, {} as any)
|
35
|
+
|
36
|
+
export const ModeNameMap = AvailablePlugins.reduce((hash, item: Plugin) => {
|
37
|
+
for (var [name, plugin] of Object.entries(item)) {
|
38
|
+
plugin.modes.forEach((mode: PluginBody) => {
|
39
|
+
hash[mode.class_namespace] = mode.display_name
|
40
|
+
})
|
41
|
+
};
|
42
|
+
return hash;
|
43
|
+
}, {} as any)
|