bf5df633f9fe5b062f57a0a7604909bf3e265f8d
[rpsls-web.git] / rpsls.js
1 const socket = io();
2
3 const getV = (field) => localStorage.getItem(field);
4
5 const Login = {
6 view: function() {
7 return m("input[type=text][placeholder=User name]", {
8 autofocus: true,
9 onchange(e) {Login.username = e.currentTarget.value},
10 onkeyup: Login.process
11 });
12 },
13 process: function(e) {
14 if (e.keyCode == 13) socket.emit("login", e.target.value);
15 }
16 };
17
18 let Seek = {
19 searching: false,
20 seekGame: function() {
21 // If not logged in, redirect
22 if (!getV("name")) m.route.set("/login");
23 else {
24 socket.emit("seek", {uid: getV("uid"), name: getV("name")});
25 Seek.searching = true;
26 }
27 },
28 view: function(vnode) {
29 if (Seek.searching)
30 return m("img.animated", {src: "assets/searching.gif"});
31 return m("button", {onclick: Seek.seekGame}, "Play");
32 }
33 };
34
35 const Choices =
36 {'r':"Rock",'p':"Paper",'s':"Scissors",'l':"Lizard",'k':"Spock",'?':"what"};
37 const Win =
38 {'r':['s','l'], 'p':['r','k'], 's':['p','l'], 'l':['p','k'], 'k':['r','s']};
39 const MAX_POINTS = 7;
40
41 let Play = {
42 gid: 0,
43 mymove: "",
44 oppmove: "",
45 myselect: "?",
46 oppselect: "?",
47 mypoints: 0,
48 oppoints: 0,
49 mnum: 0,
50 oppid: 0,
51 oppname: "",
52 gameover: false,
53 initGame: function(msg) {
54 Play.gid = msg.gid;
55 Play.oppid = msg.oppid;
56 Play.oppname = msg.oppname;
57 Play.gameover = false;
58 for (const v of ["mymove","oppmove"]) Play[v] = "";
59 for (const v of ["myselect","oppselect"]) Play[v] = "?";
60 for (const v of ["mnum","mypoints","oppoints"]) Play[v] = 0;
61 },
62 compareMoves: function() {
63 Play.oppselect = Play.oppmove; //reveal opponent's move only now
64 if (Win[Play.mymove].includes(Play.oppmove)) {
65 if (++Play.mypoints == MAX_POINTS) Play.endGame(true);
66 }
67 else if (Win[Play.oppmove].includes(Play.mymove)) {
68 if (++Play.oppoints == MAX_POINTS) Play.endGame(false);
69 }
70 Play.mnum++;
71 Play.mymove = "";
72 Play.oppmove = "";
73 },
74 endGame: function(Iwin) {
75 Play.gameover = true;
76 setTimeout(() => {
77 if (Iwin) alert("Bravo t'as gagné !");
78 else alert("Pas de chance, t'as perdu...");
79 m.route.set("/seek");
80 }, 1000);
81 },
82 playMove: function(code) {
83 if (Play.mymove || Play.gameover)
84 // I already played, or game is over
85 return;
86 Play.mymove = code;
87 Play.myselect = code;
88 socket.emit("move", {
89 uid: getV("uid"),
90 gid: Play.gid,
91 choice: Play.mymove,
92 mnum: Play.mnum,
93 oppid: Play.oppid
94 });
95 if (Play.oppmove) Play.compareMoves();
96 else Play.oppselect = "?";
97 },
98 view: function() {
99 return m("div", {},
100 [m("h2", {},
101 `${getV("name")} [${Play.mypoints}] vs. ${Play.oppname} [${Play.oppoints}]`)]
102 .concat(
103 [m(".choices", {}, [
104 m("img", {src: "assets/" + Choices[Play.myselect] + ".png"}),
105 m("img", {src: "assets/" + Choices[Play.oppselect] + ".png"})
106 ])]).concat(
107 [m(".options",
108 {style: `opacity:${Play.mymove==''?'1':'0.5'}`},
109 ["r","p","s","l","k"].map((code) => {
110 return m("img", {
111 src: "assets/" + Choices[code] + ".png",
112 onclick: () => Play.playMove(code)
113 })
114 }))])
115 );
116 }
117 };
118
119 socket.on("login", (msg) => {
120 if (!msg.err) {
121 localStorage.setItem("name", msg.name);
122 localStorage.setItem("uid", msg.uid);
123 m.route.set("/seek");
124 }
125 else alert(msg.err);
126 });
127 socket.on("play", (msg) => {
128 Seek.searching = false;
129 if (msg.oppid == getV("uid")) {
130 alert("Cannot play against self!");
131 m.redraw(); //TODO: because no DOM interaction... ?
132 }
133 else {
134 Play.initGame(msg);
135 m.route.set("/play");
136 }
137 });
138 socket.on("move", (msg) => {
139 Play.oppmove = msg.choice;
140 Play.oppselect = "?"; //not showing opponent selection yet!
141 if (Play.mymove) Play.compareMoves();
142 else Play.myselect = "?";
143 m.redraw(); //TODO... (because no DOM interactions)
144 });
145
146 m.route(document.body, "/seek", {
147 "/seek": Seek,
148 "/play": Play,
149 "/login": Login
150 });