![KDPV](https://habrastorage.org/getpro/habr/post_images/54c/0d9/b76/54c0d9b764f6483fc96c8fa5d746237a.jpg)
ããã«ã¡ã¯ãHabrãçŽ æŽãããããŒãã²ãŒã ãEvolutionïŒThe Origin of Speciesãã®ãªã³ã©ã€ã³ããŒãžã§ã³ãæžããã®ã§ãã¢ãŒããã¯ãã£ãšæè¡çãªåé¡ã«é¢ããã¡ã¢ãå ±æããããšæããŸãã ããã«æ確ã«ããŸã-宣äŒããã®ã§ã¯ãªãããšã©ãŒãšæ©èœã«ã€ããŠè©±ãããšã«èå³ãããããã®èŠè¿ãã«ãç§ã®æ±ºå®ãšã³ãŒãã«ã€ããŠå€ãã®æ°ãããŠè¯ãããšãèããŸãã
ãŸããã²ãŒã ã«ã€ããŠå°ã説æããŸãããæè¡çãªè©³çŽ°ãæ±ãã人ã®ããã«ãã¿ãã¬ã®äžã«é ããŠããŸãã
ã²ãŒã ã¯ãã«ãŒããšããŒããããã®ãããã§æ§æãããŠããŸãã å移åã¯ãã§ãŒãºã«åããããŸãïŒ
éçºãã§ãŒãºïŒãã¹ãŠã®ã«ãŒããé çªã«é 眮ããŸãã ã«ãŒãã¯2éãã®æ¹æ³ã§é 眮ã§ããŸã-ã·ã£ãã®å Žåãåç©ã®å ŽåããŸãã¯æ¢åã®ãã®ã®ããããã£ãšããŠã
é£åãã§ãŒãºïŒæåã®ãã¬ã€ã€ãŒã¯ãµã€ã³ãã転ããã飌æããããé£åãããã«å ¥ããŸãã é çªã«ãåãã¬ã€ã€ãŒã¯ãããããããã1ã€åãåãããããèªåã®åç©ã«äžããŸãã
çµ¶æ» ãã§ãŒãºïŒååãªé£æããªãã£ãåç©ã¯æ»ã«ããã¬ã€ã€ãŒã¯ãããããæ°ããã«ãŒããåãåããæåããããçŽããŸãã
ããããçµãããšã誰ããåç©ãšèç©ããã財ç£ã®ãã€ã³ããæ°ããŸãã
ããããã£ã¯éåžžã«ç°ãªããŸããããã¹ãŠããªã¹ãããããã§ã¯ãããŸããããããã€ãäŸãæããŸãããèèªäºåãïŒåç©ã¯è¿œå ã®é€ã®ããŒã¯ã³ãåããå®éã«èèªäºåãšããŠã延æãã§ãããããç©ºè ¹ã®åãã§çãæ®ãããšãã§ããŸãã ãŸãã2ã€ã®ã¿ã€ããã€ãªããã¢ã®ããããã£ããããŸããããšãã°ããååãïŒ1å¹ã®åç©ãé£ç©ãåãåããšã2å¹ç®ã¯é£ç©ããããç¡æã§åãåããŸãã
1ã€ã¯ãç¹å¥ãªããããã£ãPredator +1ãã§ããåç©ã¯çãæ®ãããã«ãã1ã€ã®é£ç©ãå¿ èŠãšããŸãããä»ã®åç©ãæ»æããŠé£ã¹ãããšãã§ããŸãã
å®éãããã¯ã²ãŒã ã§ã-é£ç©ããããåãã ãã§ãªããæé£è ãã身ãå®ãããã«ãã
ããå€ãã®äŸãå¿ èŠãªå Žå-ã€ãŸãããBig +1ãïŒå€§ããªåç©ã«ã¯è¿œå ã®é£ç©ãå¿ èŠã§ãããåãç¹æ§ãæã€æé£è ã®ã¿ããããé£ã¹ãããšãã§ããŸãïŒãŸãã¯ãCamouflageã ã
ããã©ãµã€ã+2ããªã©ã®äžéšã¯ã察æŠçžæã®åç©ã«ã®ã¿ã¬ã€ã¢ãŠãã§ãããã®åŸã圌ã¯ããã«2ã€ã®ããŒãããããå¿ èŠãšããããã圌ã®çåãè€éã«ããŸãã
äžè¬ã«ãã²ãŒã ã«ã¯ããªãåçŽãªåºæ¬ã«ãŒã«ããããŸããããã¹ãŠã®çžäºäœçšãèšç®ããããšã¯éåžžã«èå³æ·±ããæã«ã¯è€éã§ãã ãããšã¯å¥ã«ãè¿œå ã«ã€ããŠèšåãã䟡å€ããããŸããããã¯çŽ3ã€ã®éšåã§ããããã¹ãŠãéããŸã«ããŸãã ã€ãŸããæåã®ããããã£ããŸã æ£åžžã§ããå Žåã9ã€ã®æ°ããããããã£ãè¿œå ããŸãïŒããªãããŒãªã¡ã«ããºã ã¯ãããŸããïŒã次ã«ã2çªç®ã®å€§éžã¯ãããŒãã«ã3ã€ã®éšåã«åå²ããã²ãŒã å šäœã3ã€ã®ç°ãªã倧éžã§è¡ãããŸãã ãŸãããæ€ç©ãã¯ã²ãŒã ãããã¥ãŒããåé€ããå¶åŸ¡å¯èœãªæ€ç©ããã£ãŒãããŒã¹ã«ãªããŸãã
ã ãããä»ããããžã§ã¯ãã«ã€ããŠãç§ã¯ã«ããã®äžã«ãããé ããŸãããããªãã¯ããã®ããã«æ¥ãŸããïŒ
äžåºŠãç§ã¯ãŸã æ°ããReactãšReduxãç 究ããããšã«æ±ºããŸãã...ããããããã«å§ããã®ã¯ééã£ãŠããŸãããŸããç§ã®äººçã«å°ãªããšã1ã€ã®ã²ãŒã ãè¿œå ãããããžã§ã¯ããäžè¬ã«ä¿åããããšã«ã€ããŠïŒ
ãã¹ã
![](https://habrastorage.org/files/b28/b53/1df/b28b531dfc91442d88b5b282b7d91f63.png)
å®éãç§ã¯ä»äºã®åŸã®å€ã«æžããŠããããã¡ããæ¯æ¥ã§ã¯ãããŸãããã1ãæåŸã§ãäœãèŠããŠããªããããžã§ã¯ããéããŠãéãã«å¥ã®æ©èœã®ã³ãŒãã£ã³ã°ãéå§ã§ããŸããã åºæ¬çã«æ¬¡ã®ããã«ãã¹ãããã®ã§ããŠããããã¹ããååŸãããã©ããã¯ããããŸããã
it('User0 creates Room, User1 logins', () => { const serverStore = mockServerStore(); // mock, , middleware const clientStore0 = mockClientStore().connect(serverStore); // mock const clientStore1 = mockClientStore().connect(serverStore); // clientStore0.dispatch(loginUserFormRequest('/test', 'User0', 'User0')); // clientStore0.dispatch(roomCreateRequest()); const Room = serverStore.getState().get('rooms').first(); clientStore1.dispatch(loginUserFormRequest('/test', 'User1', 'User1')); expect(clientStore0.getState().get('room'), 'clientStore0.room').equal(Room.id); expect(clientStore0.getState().getIn(['rooms', Room.id]), 'clientStore0.rooms').equal(Room); expect(clientStore1.getState().get('room'), 'clientStore1.room').equal(null); expect(clientStore1.getState().getIn(['rooms', Room.id]), 'clientStore1.rooms').equal(Room); });
ã€ãŸããäžæ¹ã§ã¯æãå€ç«ããæ©èœããã¹ãããããšããŸããããããäžæ¹ã§ã¯ã¯ã©ã€ã¢ã³ãã§ã¢ã¯ã·ã§ã³ããã£ã¹ãããããããèªäœããµãŒããŒã«ãéä¿¡ãããå¿çãåãåããã«ãŒã ã®äœæã®ã¿ããã§ãã¯ããŸãã
ãšããã§ãããªããæ°ã¥ããå Žå-ç§ã®ãã¹ãã¯åæçã§ãããsocket.ioã®åæã¢ãã¯ã®ããã«åäœããŸãã ç§ã¯npmã§ãã®ãããªãã®ãèŠã€ããããªãã£ãã®ã§ãèªè»¢è»ã«ä¹ããŸããã ããããå®éãããã¯éåžžã«ç©è°ãéžãç¹ã§ãããªããªãããããžã§ã¯ãå šäœãåæããå¿ èŠãããããã§ãããããããã¹ãŠã®ãããã«ã€ããŠKISSã«çããŸãã ãã¡ãããéåæãã¹ãïŒasync / awaitã䜿çšïŒã«ãã¹ãŠãæžãçŽãããšããŸããããã¯ã©ã€ã¢ã³ãã®ãã£ã¹ãããã¯ãµãŒããŒããã®çŽæãäžããªããã°ãªããããã¹ãã®ããã ãã«ãããã¯ãŒã¯ããã«ãŠã§ã¢ããããå¿ èŠãããããšã«æ°ä»ããŸããããã©ãããããããã¹ãŠãå€æŽããããããŸããã ãã ããçè«çã«ã¯ããã¯å¯èœã§ãã
ããé«åºŠãªãã¹ãã®äŸïŒ
Predatorããããã£ãæã€ã¯ãªãŒãã£ãŒãMimicryããããã£ãæã€ã¯ãªãŒãã£ãŒãæ»æãããšãå¯èœã§ããã°ãåããã¬ã€ã€ãŒã®å¥ã®ã¯ãªãŒãã£ãŒã«æ»æããªãã€ã¬ã¯ãããŸãã
it('$A > $B m> $C', () => { // A B, C const [{serverStore, ParseGame}, {clientStore0, User0, ClientGame0}, {clientStore1, User1, ClientGame1}] = mockGame(2); // mockGame( ) [{serverStore, ParseGame}, ... ] // ParseGame yml ID' . // . const gameId = ParseGame(` phase: 2 // ( ) food: 10 // = 10 , players: // - continent: $A carn // id "$A" , TraitCarnivorous, . - continent: $B mimicry, $C // - ID "$B" , ID "$C". `); const {selectAnimal, selectTrait} = makeGameSelectors(serverStore.getState, gameId); // reselect ( ), expect(selectTrait(User1, 0, 0).type).equal('TraitMimicry'); // , . // "" clientStore0.dispatch(traitActivateRequest('$A', 'TraitCarnivorous', '$B')); expect(selectAnimal(User0, 0).getFoodAndFat()).equal(2); // expect(selectAnimal(User1, 0).id).equal('$B'); // expect(selectAnimal(User1, 1)).undefined; // = . });
æš¡å£ã®ããã®7ã€ã®ãã¹ãããããŸãïŒ
Aã¯æ¬æ ã§Bãæ»æããCã¯ã«ã¢ãã©ãŒãžã¥ã§æ»æããŸãïŒBã¯æ»æãèŠããªãããCã«ãªãã€ã¬ã¯ãã§ãããAã¯Bãé£ã¹ãŸãïŒ
Aã¯æš¡å£ã§Bãæ»æããCã®ã¿ïŒäžèšã®å ŽåïŒ
AïŒãã¬ãã¿ãŒïŒãBïŒæ¬æ ïŒãCïŒæ¬æ ïŒïŒAã¯Bãæ»æããBã¯æ»æãCã«ãªãã€ã¬ã¯ãããCã¯æ»æãBã«ãªãã€ã¬ã¯ãããŸãããã²ãŒã ã¯ç¡éãµã€ã¯ã«ã«å ¥ããŸããããããŠAã¯Bãé£ã¹ãŸã
AïŒæé£è ïŒãBïŒæ¬æ ïŒãCãDïŒAã¯Bãæ»æããã²ãŒã ã¯ãã¬ã€ã€ãŒ2ã«ã©ã®ã¯ãªãŒãã£ãŒïŒCãŸãã¯DïŒãçãlikeã«ãããããå°ããŸãã 圌ã¯ãã®Cã«çããAã¯Cãé£ã¹ãã
AïŒæé£è ïŒãBïŒæ¬æ ïŒãCïŒæ¬æ ïŒãDïŒAã¯Bãæ»æããã²ãŒã ã¯ãã¬ã€ã€ãŒ2ã«ãã©ã®ã¯ãªãŒãã£ãŒïŒCãŸãã¯DïŒãç ç²ã«ãããããå°ããŸãã 圌ã¯ãCãåã³æš¡å£ããããšãè¿ä¿¡ããã²ãŒã ã¯ãä»åãã©ã®ã¯ãªãŒãã£ãŒïŒBãŸãã¯DïŒãçãwillã«æ§ããã®ããããäžåºŠå°ããŸãã ãã¬ã€ã€ãŒã¯Bãšå¿çããããã¯æ»ã«ãŸãã
AïŒæé£è ïŒãBïŒæ¬æ ïŒãCãDïŒAã¯Bãæ»æããã²ãŒã ã¯ãã¬ã€ã€ãŒ2ã«ã©ã®ã¯ãªãŒãã£ãŒïŒCãŸãã¯DïŒãçãlikeã«ãããããå°ããŸãã ãããã圌ã¯çãããã²ãŒã èªäœã誰ã殺ããã決å®ããŸãã
åã®ãã®ãšåæ§ã§ããã1msã®å²ãåœãŠãããæéééã«å¯ŸããŠãã¬ãŒã€ãŒã責任ãè² ããªãéåæãã¹ã ã ããã¬ã€ã€ãŒãå¿çããªãã£ãããšããŠãç§ã¯await new Promise(resolve => setTimeout(resolve, 1));
ã䜿çšããŸãawait new Promise(resolve => setTimeout(resolve, 1));
ãããŠæåŸã®ãã¹ãã¯ãã©ãããäœããã®ãã°ã«é¢é£ããŠããããã§ãïŒæ¬æ ãæã€ã¯ãªãŒãã£ãŒãæ¢ããåŸãæ°ããã©ãŠã³ããå§ãŸãããšããã§ãã¯ããŸãã çç±ã¯èŠããŠããŸããã
ãªãããã ããªã®ã§ããïŒ ãã®äžãç§ã¯ã©ããã§ç§ã®æš¡å£ãæ£ããåäœããªãããšãå¿é
ããããšã¯ã§ããŸããã ç©ããã質åãã®ããžãã¯å
šäœãæžãçŽãããšãã§ãããã¹ãã§ã¯ 倱æãã ãã¹ãŠãæ©èœããŸãã
ãããã£ãŠããšããã§ã詳现ã確èªããªãã§ãã ããã Cãæ»äº¡ãããAãé£ç©ãåãåã£ããªã©ãææãªè«çççµæã®ã¿ äžåºŠãç§ã¯ããã€ãã®é ããããã©ã¡ãŒã¿ãŒããã§ãã¯ããããšããŸããïŒããšãã°ããã¬ãŒã€ãŒã«ã¯ããããããšãããã©ã°ããããŸãïŒããããããã®çµæããã¬ãŒã€ãŒãåã³äŒŒåããªãããšã確èªãå§ããŸããã
ç§ã®ãããžã§ã¯ããç¹ã«èªå® ã®ãããžã§ã¯ãã§ã¯ããã¹ãã§ããžãã¯å šäœããã¹ãããããšããå§ãããŸãã å®å®æ§ã®åäžã«å ããŠããããžã§ã¯ããžã®åŸ©åž°ã«ã圹ç«ã¡ãŸãã
ã¯ã©ã€ã¢ã³ããã¹ãã«ã€ããŠã¯å¥ã«-ããã§ã¯ãã¹ãŠãããã»ã©ãã©è²ã§ã¯ãªãã®ã§ãã¯ã©ã€ã¢ã³ããé »ç¹ã«æžãçŽãã4åç®ä»¥éã¯æžã蟌ã¿ãåæ¢ããŸããã
顧客ãšãã¶ã€ã³ã
ãããŠä»ãã¯ã©ã€ã¢ã³ãã®ã²ãŒã ã®éšåã¯ç§ã«ã¯ãŸã£ããåããªãããç§ã¯ãã以äžè¯ããã®ãèããããªãã çæ³çã«ã¯ããåªãããã¶ã€ã³ã®å€å žçãªåçãšãæè¡ãšç§åŠã®é©æ°ãšå¯èœæ§ãçµ±åãããã¯ãŒã«ãªãèŠèŠçèšèªããåãããMaterial UI Hearthstoneããå ¥æããå¿ èŠããããŸãã ã¯ããã« ããã ããRobotoãäžå€®ã«ããç°è²ã®åè§åœ¢ã衚瀺ãããŸããã ããããå®éããã¶ã€ã³ã¯ãŸã£ããç§ãåæºãããŸãããããããŒãã«ãèªäœãã«ãŒããé£ã¹ç©ãçãç©ãããå ŽæããããŸãã ãããŠãããã«å®å šãªç¶ãç®ããããŸãããã¹ãŠã®æ å ±ã«å¯Ÿå¿ã§ããªããšããäºå®ããå§ãŸããé説çã«ãç§ã¯å€ãã®ç©ºãã¹ããŒã¹ããããšããäºå®ã§çµãããŸãã
ããã«åé¡ããããŸãããŸããç§ã¯å«ãªãã¶ã€ããŒã§ãããã¹ã¿ã€ã«ããã¯æ®å¿ãªããšã奜ã¿ãŸãã 第äºã«ãç§ã¯æ ãè ã§ãã ãããŠç¬¬äžã«ãã²ãŒã èªäœã«è±ãå ¥ããããŸã-ãã¬ã€ã€ãŒã¯1äœãŸãã¯20äœã®ã¯ãªãŒãã£ãŒãæã€ããšãã§ããŸãã ãŸãã1ã20åã®ããããã£ãæã€ããšãã§ããŸãã ãããŠããã¬ã€ã€ãŒèªèº«-2ãã8ãŸã§ã ãã®ãããæ°åã®ãªããžã§ã¯ãããæ°çŸåã«ã¹ã±ãŒã«ããæ£æ°ãªãã®ãäœãæ¹æ³ãæ³åããããšã¯ã§ããŸããã ãããŒãã²ãŒã ã®ãããªããšããååãåãããããŒã¹ã¹ããŒã³ã®ãããªããã¹ãŠã®ããšãè¡ããªãã·ã§ã³ã¯ãããããããã§ã¯æè¯ã§ã¯ãããŸããã
åå¿ãã
èŠãç®ã¯ãŸããŸãã§ãããåäœããŸãããããReactãšãã®æ±ºå®è«ã®å€§ããªã¡ãªããã§ãã
![決æã§ããªããæºãããŸã](https://habrastorage.org/getpro/habr/post_images/7dd/36f/fc5/7dd36ffc57e8f5d7c920b3a71ebbf1fa.jpg)
ããŒãMVC / MVVMã®æå¿ã¯å¿ ãããååã§ã¯ãããŸããããReactã¯å€éšã®ãã¹ãŠã®ããžãã¯ã匷å¶çã«åé€ããç¶æ XïŒèªèããããïŒã§UIããã®ããã«ãªãããã«ããŸãã 誰ãããèªãã ããã«ããReactã¯ç¶æ ãååŸããŠUIãè¿ãé¢æ°ã§ããã Reduxãšäœµçšããããšã§ãå¯äœçšãšã確å®æ§ã§æºãããããããšããªããªããŸããäœããã©ãã§ããã€èµ·ãããã¯ç¢ºå®ã§ãã ããã¯éåžžã«ã¯ãŒã«ã§ããå ããŠãjsxã«å«æªæãæããããšã¯ãããŸãããéã«ã{ïŒ < {{x | filterïŒ sdfsdf}} >ïŒ }ãŸããã¹ã³ãŒããå®çŸ©ããå¿ èŠã¯ãããŸããã vueãšangle 2ã§ãããã©ã®ããã«äœ¿çšãããããããŸããããæåã¯ããããã®ã¹ã³ãŒãã§ãã ãããŠäžè¬çã«ã¯ãåæ¹èšå ¥ããæ¹ãç°¡åã§ãã
ããŠãããŒã¿ã«ãªã©ã®ããããçš®é¡ã®æ©èœãç§ãçŽæããŸããã 確ãã«ãç§ã¯éšå±ã®ã³ã³ããŒãã³ããæžããŠããŸãããã®äžã®ããããŒã«äœããåºããŠã¿ãŸãããïŒ ããã«ããã·ã¥ããªãã§ãã ããããã ããã³ã³ããŒãã³ã<PortalTarget name='header'/>
ããã«ååšããå Žåã®ã¿
export class Room extends Component { ... render() { const {room, roomId, userId} = this.props; return (<div className='Room'> <Portal target='header'> <RoomControlGroup inRoom={true}/> // <= Header' </Portal> <h1>{T.translate('App.Room.Room')} «{room.name}»</h1> <div className='flex-row'> <Card className='RoomSettings'> <CardText> <RoomSettings {...this.props}/>
å€èšèªäž»çŸ©ã¯i18n-reactãä»ããŠè¡ãã®ãæã䟿å©ã§ããããã«æããŸãããèšèšã§ã¯ãreact-mdlã䜿çšããŠããŸãã æãã¿ãæ£ãã°ããããæã®å¥ã®å ç·ãç§ã¯åå¿ããã©ã€ãã©ãªã«éããŸããããã¯ã¯ãŒã«ã§ãã
ãã ããReactã«ã¯ãã€ãã¹ã®ã¢ãã¡ãŒã·ã§ã³ããããŸãã CSSãã©ã³ãžã·ã§ã³ãããè€éãªãã®ã¯ãããã»ã©åçŽã§ã¯ãããŸããã ã¯ããç¶æ ã¯1ã§ãããUIã¯ç°ãªãã¯ãã§ãã
æªç©-AnimationServiceãçæããŠããã®åé¡ãå«ãªæ¹æ³ã§è§£æ±ºããŸããã ã€ãŸãã圌ã¯ããã«ãŠã§ã¢ãã¯ã©ã€ã¢ã³ãã«ããããããã¹ãŠã®ã¢ã¯ã·ã§ã³ããã£ããããŠæåã®ã¢ã¯ã·ã§ã³ã®ã¢ãã¡ãŒã·ã§ã³ãéå§ããæ®ãããã¥ãŒã«å ¥ããã¢ãã¡ãŒã·ã§ã³ãå®äºãããšããã«æ¬¡ã®ã¢ã¯ã·ã§ã³ãèµ·åããŸãã ããšãã°ãã«ãŒããããªãã®æã®äžã«çŸããé£ãã§ããéãã²ãŒã ãçµäºããããšãã§ããªããšããäºå®ã§ãããã¯å€ãã®ãã°ãäžããŸãã
äžæ¹ã次ã®ãããªVelocity.jsã䜿çšããŠã³ã³ããŒãã³ããã¢ãã¡ãŒã·ã§ã³åã§ããŸãã
export const createAnimationServiceConfig = () => ({ // , animations: ({subscribe, getRef}) => { // subscribe - Action, getRef - // : subscribe(" ", (done ( ), actionData, getState) => { // ...
å®éãç§ã¯ãããç¡é§ã«æžããŸãããããã®ã¢ã³ã¹ã¿ãŒã䟿å©ã«ãªã£ãå¯äžã®ã¢ãã¡ãŒã·ã§ã³ã¯ã«ãŒãã®é åžã§ãïŒãã ããHearthstone !! 11ã®ããã«ïŒïŒãããã§ååã§ãã
ãã®ãããäžè¬çã«ãReactã䜿çšãããšãã»ãšãã©ãã¹ãŠãããŸããããŸããããã¯ãäž»ã«åœŒãèªåã®ããžãã¹ã«åå ¥ããã®ã§ã¯ãªããReduxãããžãã¯ãæ±ãããã§ãã
Redux
ã¯ã©ã€ã¢ã³ããšãµãŒããŒã®äž¡æ¹ã§ãã¹ãŠã®äœæ¥ãè¡ãã®ã¯åœŒã§ãã ããã«ãsocket.ioã®ããã«ãŠã§ã¢ãä»ããŠäºãã«éä¿¡ããŸãã ç§ã¯ããçš®ã®RPCãäœæããŸãããããã¯æ¬¡ã®ããã«èŠããŸãïŒæºåãã§ããŸãããããã§game.jsãã倧éã®ã³ãŒããäœæãããŸã ïŒ
// Game Create // Request , export const gameCreateRequest = (roomId, seed) => ({ type: 'gameCreateRequest' // , , , data: {roomId, seed} // , meta: {server: true} // Middleware }); // , const gameCreateSuccess = (game) => ({ type: 'gameCreateSuccess' , data: {game} }); // - const gameCreateNotify = (roomId, gameId) => ({ type: 'gameCreateNotify' , data: {roomId, gameId} }); // export const server$gameCreateSuccess = (game) => (dispatch, getState) => { // Store dispatch(gameCreateSuccess(game)); // Notify, dispatch(Object.assign(gameCreateNotify(game.roomId, game.id) , {meta: {users: true}})); // . selectPlayers4Sockets(getState, game.id).forEach(userId => { dispatch(Object.assign(gameCreateSuccess(game.toOthers(userId).toClient()) , {meta: {userId, clientOnly: true}})); }); // , , , . // - : // dispatch(Object.assign( // gameCreateSuccess(game.toOthers(null).toClient()) // , {meta: {clientOnly: true, users: selectPlayers4Sockets(getState, game.id)}} // )); // .¯\(°_o)/¯ }; // ... 40 ... // : export const gameClientToServer = { gameCreateRequest: ({roomId, seed = null}, {userId}) => (dispatch, getState) => { // , , dispatch(server$gameCreateSuccess(game)); } // ... } export const gameServerToClient = { // , gameCreateSuccess: (({game}, currentUserId) => (dispatch) => { dispatch(gameCreateSuccess(GameModelClient.fromServer(game, currentUserId))); dispatch(redirectTo('/game')); }) ... }
gameClientToServerãªããžã§ã¯ãã¯ããµãŒããŒãåä¿¡ã§ããã¢ã¯ã·ã§ã³ã§æ§æãããŠããããããshutdownServerãã¿ã€ãã®ã¢ã¯ã·ã§ã³ãçŽæ¥éä¿¡ããããšã¯ã§ããŸããã ãããŠãã®éã¯ãåã«JSONãªããžã§ã¯ãããããã€ãã®ã¢ãã«ãŸãã¯äœããå®éã«ã¢ãã«ã«å€æããŸãã
次ã®ããã«æ©èœããŸãã
1ïŒãŠãŒã¶ãŒããã²ãŒã ãéå§ããã¿ã³ãæŒããŸãã
2ïŒReact-reduxãã£ã¹ãããgameCreateRequestã¢ã¯ã·ã§ã³
3ïŒã¯ã©ã€ã¢ã³ãããã«ãŠã§ã¢ïŒ
const nextResult = next(action); if (action.meta && action.meta.server) { action.meta.token = store.getState().getIn(['user', 'token']); socket.emit('action', action); } return nextResult;
nextResultã¯ãã¹ãïŒåæã§ããããšãæãåºããŸãïŒã«å¿ èŠã§ããsocket.emitïŒïŒã®åŸã«nextïŒã¢ã¯ã·ã§ã³ïŒãåŒã³åºããšãã¯ã©ã€ã¢ã³ãã¬ãã¥ãŒãµãŒã¯åŸã§ãµãŒããŒããå¿çãéä¿¡ããã¢ã¯ã·ã§ã³ãåŠçããŸãã
4ïŒãµãŒããŒãã¢ã¯ã·ã§ã³ãå®è¡ããŸãã
socket.on('action', (action) => { if (clientToServer[action.type]) { // clientToServer , xxxClientToServer, roomClientToServer gameClientToServer const meta = {connectionId: socket.id} // ActionCreator' id . , . if (!~UNPROTECTED.indexOf(action.type)) { // UNPROTECTED, // } const result = store.dispatch(clientToServer[action.type](action.data, meta)); // gameClientToServer.gameCreateRequest
5ïŒäžã§æžããããã«ãserver $ gameCreateSuccessãåŒã³åºãããgameCreateSuccessããµãŒããŒã«ã®ã¿ãã£ã¹ãããããã次ã«gameCreateNotifyãšgameCreateSuccessãåãã¬ãŒã€ãŒã«ãã£ã¹ããããããŸãã
6ïŒã¬ãã¥ãŒãµãŒãµãŒããŒã¯gameCreateSuccessããã£ããããã²ãŒã ãäœæããŸã
7ïŒããã«ãŠã§ã¢ãµãŒããŒã¯gameCreateNotifyããã£ãããããã¹ãŠã®ã¯ã©ã€ã¢ã³ãã«éä¿¡ããŸãïŒãã®ããããã®ãããªéšå±ã§ã²ãŒã ãéå§ãããããšãããããŸãïŒ
8ïŒãŸãã次ã®gameCreateSuccessïŒåãã¬ãŒã€ãŒã®ã²ãŒã ãå«ãïŒããã£ãããããµãŒããŒReducerã«éä¿¡ãããŸãïŒclientOnlyïŒtrueãã¡ã¿ã§æå®ãããŠããããïŒ
ããã¯ã©ããããããããã¯ãã¹ãŠåäœããŸãã
ç°å¢
ç¡æã¢ã«ãŠã³ãã®herokuappã§åäœããŸãã 6æéã®ããŠã³ã¿ã€ã ãå¿ èŠãªãããããã¯ããŸãè¯ããããŸããã ãã ããåæ»è ã®åºåžïŒã·ããªã¢ãã3人ã®ç·ãå€ãå¹³æ¥ã«ãã¬ã€ããããšãããïŒã®ãããããã¯ããŸãæ°ã«ããŸããã
ãããã£ãŠãVCçµç±ã®ãã°ã€ã³ãããŒã¿ããŒã¹ããèªã¿åãããã®ã§ã¯ãªããæ¯åå床èŠæ±ãããããšã¯æ°ã«ãªããŸããã ãã¡ããããããããã§ãããããžã§ã¯ããããŒã¿ããŒã¹ã䜿çšããã®ã«ååãªèŠæš¡ã«ãªã£ããšæã£ãããmlab.comããç¡æã®mongoããã蟌ã¿ãããã«VKããŒã¯ã³ãæžã蟌ã¿ãæ°ããããŒã¯ã³ãèŠæ±ããŸãã ãããããã€ããã°ã€ã³æã«çµ±èšæ å ±ãšOauthããŒã¯ã³ãèŠæ±ããããšã¯ãããŸãããããããŸã§ã®ãšãããããŒã¿ããŒã¹ã¯å®å šã«äœ¿ãç©ã«ãªããŸããã
ãã¹ãŠã®ã²ãŒã ã®ç¶æ ã¯reduxã«çŽæ¥ä¿åãããŸãã ã©ããã«èªåã®è²¡ç£ãããŒã¿ããŒã¹ã«ä¿åããæ²èŠ³çãªå€©æãèŠãŸããããå人çã«ã¯ãã®çç±ãããããŸããã ãã¶ãç§ã¯ééã£ãŠããŸãã
æåã®webpackã«è¡ããŸããã2çªç®ã®webpackã¯ãŸã æ®ã£ãŠããŸããã éçºã§ã¯ãã¯ã©ã€ã¢ã³ãã¯webpackMiddlewareãçµç±ãããµãŒããŒã¯nodemon + babel-nodeãçµç±ããŸãã å¯äžã®ãã€ãã¹ç¹ã¯ãããã¯ãšã³ããå€æŽããå Žåãããã³ããšã³ããåæ§ç¯ããããŸã§é·æéåŸ ããªããã°ãªããªãããšã§ãã ããŒãã®ããããªããŒããè©Šã¿ãŸããããã©ããããããæ©èœããŸããã§ããã ãããŠããªãããµãŒããŒã®ãã¹ããããŠããŸãã
ãéäŒçµ±çãªããã®ã³ã°ã«ã€ããŠç°¡åã«èšåããŸã-ãã¡ã€ã«ãžã®æžã蟌ã¿ã¯ãªãã·ã§ã³ã§ã¯ãããŸãããherokuããã¹ãŠãæ¶å»ããããããçš®é¡ã®å°éãµãŒãã¹ãäžäŸ¿ãŸãã¯ææã§ãããããwinstonã®çŽ æŽãããã¢ãžã¥ãŒã«winston-google-spreadsheetãèŠã€ããŸããã ã¯ãã圌ã¯ãã°ãGoogleã¿ã°ã«æžã蟌ã¿ãŸãã ç§ã¯åãlogglyããã奜ãã§ãã
çµè«ïŒ
æè¡ïŒ
Reactã¯æ¢ã«å€ããªã£ãŠããŸãïŒïŒtrollface :)ããå¿ã¯å€ãããç§ã®æèŠã§ã¯ãæ
£ããå¿
èŠããããŸãã
Reduxã«ã€ããŠãåãããšãèšããŸãã
åæãã¹ãã¯åªããŠããŸãããç§ã¯ãã¹ã¯ããããŸãã¯ã¿ãŒã³ããŒã¹ã®ã²ãŒã ãéåæã§çŽæéãã«å®è¡ããŸãã ã€ãŸããéä¿¡-ç§ã¯çããåŸ ã£ãŠããŸããã ããããã°ããµãŒããŒã¯ã³ãŒã«ããã¯ã¢ã¯ã·ã§ã³ãèšå®ã§ããªãããšã«æ©ãå¿ èŠããªããªããŸãã
åéã¯Map'amiãŸãã¯ãªããžã§ã¯ãã«ãã£ãŠè¡ãããå¿ èŠããããŸãã ãããããKISSãåç©ããªã¹ãã«ä¿åã§ããã®ã«ããªãåç©ããããªããžã§ã¯ããå¿ èŠãªã®ããšæããŸããã ãã®çµæãgame.getAnimalByIdã¯é åæ€çŽ¢ãå®è¡ããŸãã ã¯ããééãã§ããç§ã¯æ¥ããããæããŸãããã€ãæžãçŽããŸãã
人éçïŒ
ãŸãããã¹ã¯ãããããªã³ã©ã€ã³ã§ç¿»èš³ããããšã¯ããããããä»äºã§ãã å€ãã®åŸ®åŠãªç¹ãšã«ãŒã«ããããšããæå³ã§ãã»ãã®æ°èªã§ãã¬ã€ã€ãŒéã§æ±ºå®ãããããšã¯ãã¡ã¬ãã€ãã®ã³ãŒãããªã¯ãšã¹ããæŸèæã«å€ãããŸãã ãŸãããã¹ã¯ãããã²ãŒããŒã¯ãå®è¡ã§ããªãäºçŽ°ãªããšã«ãåžžã«äžæºãæ±ããŠããŸãã ããã«ãåžžã«ãã«ããã¬ã€ã€ãŒã§ãããã²ãŒã ãã¬ã€ãé·ãããããã¬ã€ã€ãŒã¯ã»ãšãã©ããŸããã
第äºã«-ç§ã¯ééã£ãã²ãŒã ãåããŸããã é²åã®äž»ãªé£ãããšã²ãŒã ãã¬ã€ã¯ãçµã¿åãããšãããã®çžäºäœçšãèšç®ããããšã§ãã ã³ã³ãã¥ãŒã¿ãŒã¯ããèªäœã®èšç®ãã¹ããã¹ãŠåãé€ãããŠãŒã¶ãŒã¯ããã€ãã®ãªãã·ã§ã³ããããéžæã§ããŸããã ãããã£ãŠãã²ãŒã ãã¬ã€ã¯ç Žå£ãããŸããããäºåã«èããŠããå¿ èŠããããããæªåé«ãç Žå£ãããŸãã ãŸããèè ã®ãããã§ã圌ãã¯ãã¹ãŠãéããŸã«ããã¢ããªã³ã«æºè¶³ããŠããŸãã ã€ãŸãããã¬ã€ã€ãŒã«ã¯åç©ããã1ã€ã®ã倧éžããããããã®åŸ3人ããããããŸããã ãã£ãããïŒ ãããããïŒ ã²ãŒã ã®ååãæžãæããŸãããããã¯ãïŒD
èŠçŽãããšãç§ã¯èªåã欲ãããã®ãæã«å ¥ããŸããã ç§ã®æèŠã§ã¯ããã®ã³ãŒãã¯å Žæã«ãã£ãŠã¯çŸãããããããŸãããäžè¬çã«ã¯å«ã§ã¯ãããŸããïŒãã¡ããAnimationServiceãé€ãïŒã ããã§ã¯ããã©ãŒã¯/ãã«ãªã¯ãšã¹ãã®éä¿¡/éçºã®ãã«ã/åé¡ã®æçš¿/ru-ru.jsonã®è±èªãžã®ç¿»èš³/ãã¶ã€ã³ã®ãã«ãïŒãããã¯ãŸã 埮åŠãªãã³ãã§ã¯ãããŸããïŒãããããçš®é¡ã®ãããã¹ã¿ãŒã«ã€ããŠèãããã¹ãŠã®ããšãèšãããšãã§ããŸãæ¬lyãªåå£ãªèª€è§£ã«ç»ãã¿ã©ã ç§ãPRã«å ¥ããªãããã«ãã³ã¡ã³ãã«ãµã€ããžã®ãªã³ã¯ãã¹ããŒããŸãã