Commit | Line | Data |
---|---|---|
5f918a27 BA |
1 | <template lang="pug"> |
2 | div | |
3 | input#upload(type="file" @change="upload") | |
4 | button#uploadBtn( | |
5 | @click="uploadTrigger()" | |
6 | aria-label="store.state.tr['Upload a game']" | |
7 | ) | |
8 | img.inline(src="/images/icons/upload.svg") | |
9 | </template> | |
10 | ||
11 | <script> | |
1ef65040 | 12 | import { getRandString } from "@/utils/alea"; |
5f918a27 BA |
13 | export default { |
14 | name: "my-upload-game", | |
15 | methods: { | |
16 | uploadTrigger: function() { | |
801e2870 BA |
17 | document.getElementById("upload").click(); |
18 | }, | |
19 | upload: function(e) { | |
20 | const file = (e.target.files || e.dataTransfer.files)[0]; | |
21 | var reader = new FileReader(); | |
22 | reader.onloadend = ev => { | |
23 | this.parseAndEmit(ev.currentTarget.result); | |
24 | }; | |
25 | reader.readAsText(file); | |
26 | }, | |
1ef65040 BA |
27 | parseAndEmit: async function(pgn) { |
28 | let game = { | |
29 | // Players potential ID and socket IDs are not searched | |
30 | players: [ | |
31 | { id: 0, sid: "" }, | |
32 | { id: 0, sid: "" } | |
33 | ] | |
34 | }; | |
35 | const lines = pgn.split('\n'); | |
36 | let idx = 0; | |
37 | // Read header | |
38 | while (lines[idx].length > 0) { | |
39 | // NOTE: not using "split(' ')" because the FEN has spaces | |
40 | const spaceIdx = lines[idx].indexOf(' '); | |
41 | const prop = lines[idx].substr(0, spaceIdx).match(/^\[(.*)$/)[1]; | |
42 | const value = lines[idx].substr(spaceIdx + 1).match(/^"(.*)"\]$/)[1]; | |
43 | switch (prop) { | |
44 | case "Variant": | |
45 | game.vname = value; | |
46 | break; | |
47 | case "Date": | |
48 | game.created = new Date(value).getTime(); | |
49 | break; | |
50 | case "White": | |
51 | game.players[0].name = value; | |
52 | break; | |
53 | case "Black": | |
54 | game.players[1].name = value; | |
55 | break; | |
56 | case "Fen": | |
57 | game.fenStart = value; | |
58 | break; | |
59 | case "Result": | |
60 | // Allow importing unfinished games, but mark them as | |
61 | // "unknown result" to avoid running the clocks... | |
62 | game.result = (value != "*" ? value : "?"); | |
63 | break; | |
1ef65040 BA |
64 | case "Cadence": |
65 | game.cadence = value; | |
66 | break; | |
67 | } | |
68 | idx++; | |
69 | } | |
fef153df BA |
70 | // Always generate random ID for imported games, because they could be |
71 | // downloaded at different states (prefix 'i' for 'Import'). | |
72 | game.id = 'i' + getRandString() | |
73 | if (!game.cadence) | |
1ef65040 BA |
74 | // Provide a random cadence, just to be sure nothing breaks: |
75 | game.cadence = "1d"; | |
1ef65040 BA |
76 | game.chats = []; //not stored in PGN :) |
77 | // Skip "human moves" section: | |
78 | while (lines[++idx].length > 0) {} | |
79 | // Read moves | |
80 | game.moves = []; | |
81 | await import("@/variants/" + game.vname + ".js") | |
82 | .then((vModule) => { | |
83 | window.V = vModule[game.vname + "Rules"]; | |
84 | while (++idx < lines.length && lines[idx].length > 0) { | |
fef153df BA |
85 | const spaceIdx = lines[idx].indexOf(' '); |
86 | const skipMoveNum = lines[idx].substr(spaceIdx + 1); | |
87 | const lineParts = skipMoveNum.split(","); | |
88 | let move = []; | |
89 | lineParts.forEach(lpart => { | |
90 | const smParts = lpart.split(' '); | |
91 | const startEnd = smParts[0].split('.'); | |
92 | let sm = {}; | |
93 | sm.start = | |
94 | startEnd[0] != "-" | |
95 | ? V.SquareToCoords(startEnd[0]) | |
96 | : { x: -1, y: -1 }; | |
97 | sm.end = | |
98 | startEnd[1] != "-" | |
99 | ? V.SquareToCoords(startEnd[1]) | |
100 | : { x: -1, y: -1 }; | |
101 | const appearVanish = smParts[1].split('/').map(av => { | |
102 | if (av == "-") return []; | |
103 | return av.split('.').map(psq => { | |
104 | const xy = V.SquareToCoords(psq.substr(2)); | |
105 | return { | |
106 | x: xy.x, | |
107 | y: xy.y, | |
108 | c: psq[0], | |
109 | p: psq[1] | |
110 | }; | |
111 | }); | |
1ef65040 | 112 | }); |
fef153df BA |
113 | sm.appear = appearVanish[0]; |
114 | sm.vanish = appearVanish[1]; | |
115 | move.push(sm); | |
1ef65040 | 116 | }); |
fef153df | 117 | if (move.length == 1) move = move[0]; |
1ef65040 BA |
118 | game.moves.push(move); |
119 | } | |
120 | this.$emit("game-uploaded", game); | |
121 | }); | |
5f918a27 BA |
122 | } |
123 | } | |
124 | }; | |
125 | </script> | |
126 | ||
127 | <style lang="sass" scoped> | |
128 | input#upload | |
129 | display: none | |
130 | ||
73f8753f BA |
131 | button#uploadBtn |
132 | display: block | |
133 | margin: 0 auto | |
134 | ||
5f918a27 BA |
135 | img.inline |
136 | height: 22px | |
137 | @media screen and (max-width: 767px) | |
138 | height: 18px | |
139 | </style> |