ç§ã¯ãã©ãŠã¶ãŒã²ãŒã ãRubyã§éçºããŠãããããèšèªã®æ¡åŒµãšçµã¿èŸŒã¿DSLïŒRubyã䜿çšãããšãããéåžžã«ããŸãè¡ãããšãã§ããŸãïŒãããã³è€éãªã²ãŒã ã¡ã«ãã¯ã¹ã«é¢é£ããããèšèªã®äœæã®äž¡æ¹ã«LOPããã䜿çšããŸãã ãã®èšäºã§ã¯ãã¡ã€ã³èšèªã®åçŽãªæ¡åŒµæ©èœã§ããçµã¿èŸŒã¿mini-DSLãšã2ã€ã®éçµã¿èŸŒã¿èšèªã«ã€ããŠèª¬æããŸãã ç§ã¯èªåã«è¿ããããã¯ã§äŸãæããŸããããããããªãç解ã§ããããšãé¡ã£ãŠããŸãã
ãã®èšäºã¯CrazyPit habrayuzerã«ãã£ãŠæžãããŸãããã圌ã«ã¯å ¬éããã«ã«ãããããŸããã
ã·ã³ãã«ãªèšèªæ¡åŒµ
ãªããžã§ã¯ããæäœããªããç¹å®ã®ã¢ã«ãŽãªãºã ãå®è¡ããã¯ã©ã¹ãå¿ èŠã«ãªãããšããããããŸãã ãã¡ããããã¹ãŠã®ã¡ãœãããã¡ã€ã³ã¯ã©ã¹ã«å ¥åã§ããŸãããããã¯äžå¿ èŠãªç®è©°ãŸãã«ãªããŸãã ããã«ãã¢ã«ãŽãªãºã ã¯ãã¡ã€ã³ã¯ã©ã¹ã§ã¯ãŸã£ããäžèŠãªããã€ãã®ã¡ãœãããšäŸå€ã䜿çšã§ããŸãã
ãã¬ã€ã€ãŒã¯ã圌ãç·šéããããã€ãã®ãããïŒãã¬ã€ã€ãŒãåéå¯èœãªã«ãŒãã²ãŒã ã§äœ¿çšããã«ãŒãã®ã»ããïŒãæã£ãŠããŸãã ããããã®ããããéžæããå¿ èŠããããŸã-æå¹ã«ããŸãã ãããè¡ãã«ã¯ãã¢ã¯ãã£ããŒã·ã§ã³ã¢ã«ãŽãªãºã ãå®è£ ããå¥ã®ã¯ã©ã¹ãäœæããŸãã
ããã::ã¢ã¯ãã£ããŒã¿ãŒ= Struct.newïŒïŒãããïŒ ã¯ã©ã¹ããã::ã¢ã¯ãã£ããŒã¿ãŒ def activateïŒ ...... çµãã ãã©ã€ããŒã <äžéšã®ãã«ããŒã¡ãœãããšäŸå€> çµãã
ãã®ã¢ãžã¥ãŒã«ã¯æ¬¡ã®ããã«äœ¿çšã§ããŸãã
ããã:: Activator.newïŒsome_deckïŒ.activateïŒ
ããããã¯ããã«çŸããïŒ
deck.activator.activateïŒ ïŒãŸãã¯ãã®ãã㪠deck.activateïŒ
ãããè¡ãã«ã¯ãDeckã¯ã©ã¹ã«ã¡ãœãããè¿œå ããŸãã
ã¯ã©ã¹ããã def activateïŒ ããã:: Activator.newïŒsome_deckïŒ.activateïŒ çµãã çµãã
ãããããã®ãããªã¢ã«ãŽãªãºã ãããããããã®ã§ãç§ã¯ããããªæ¹åãè¡ããŸãããããã¯æŠç¥ã¯ã©ã¹ã®ã¡ãœããã§ãïŒåãååã®ãã¿ãŒã³ã«çŽæ¥é¢ä¿ããŠããŸããïŒã ä»ãç§ã¯ãããè¡ããŸãïŒ
ã¯ã©ã¹ããã<ActiveRecord :: Base æŠç¥ïŒã¢ã¯ãã£ããŒã¿ãŒ çµãã Deck.findïŒïŒæåïŒ.activator.activateïŒ
ãŸãã¯ïŒ
ã¯ã©ã¹ããã<ActiveRecord :: Base æŠç¥ïŒã¢ã¯ãã£ããŒã¿ãŒãïŒããªã²ãŒã=> [ïŒã¢ã¯ãã£ããŒãïŒ] çµãã Deck.findïŒïŒæåïŒ.activateïŒ
ããã©ã«ãã®ã¢ã«ãŽãªãºã ã¯ã©ã¹åã¯ã<ã¡ãœãããåŒã³åºãããã¯ã©ã¹å> :: <æŠç¥ã§æå®ãããåå>ã§ãã ãã ããæåã§èšå®ã§ããŸãïŒïŒã¯ã©ã¹=> BrainDestructorïŒã
RubyèªäœãšRoRã®äž¡æ¹ã«ããã®ãããªæ¡åŒµæ©èœãå€æ°ãããŸãã Rubyã§å€ãã®ããã°ã©ãã³ã°ãè¡ã£ã人ã¯èª°ã§ã䌌ããããªããšããããšæããŸãã
å¶éã瀺ãçµã¿èŸŒã¿DSL
ã²ãŒã ã«ã¯ããŸããŸãªéšå±ãããããã¹ãŠã®äººãèš±å¯ãããŠããããã§ã¯ãããŸãããããã¬ãŒã€ãŒãç¹å®ã®èŠåãé å®ããŠããå Žåã®ã¿ã§ãã ããšãã°ãã¬ãã«ã10ãè¶ ããŠãããããããå ã®ã«ãŒãã®æ°ã8ãè¶ ããŠããŸããããã®ãããªå¶éã¯çµã¿åããããŠããŸãã ããšãã°ãããã¬ã€ã€ãŒã¬ãã«> = Nããªã©ã®å¶éã®çš®é¡ããããããã¬ã€ã€ãŒã¬ãã«> = 13ããšããç¹å®ã®å¶éããããŸãã
DSL define_constraintã䜿çšããŠå¶çŽã®ã¿ã€ããæå®ããå¶çŽãšãã®çµã¿åãããããŒã¿ããŒã¹ã«ä¿åã§ããŸãã
define_constraint "deck_sum_between"ã "ïŒ NãšïŒ Mã®éã®ã«ãŒãã¬ãã«ã®åèš" do ïŒåŒæ°['N']ãto_i..arguments ['M']ãto_iïŒ.includeïŒïŒcontext.deck.sum_of_card_levelsïŒ çµãã define_constraint "deck_without_duplicates"ã "ãã€ã¯ã®ãªãããã"㯠ïŒcontext.deck.has_duplicatesïŒ çµãã define_constraint "user_level_ge"ã "ãã¬ã€ã€ãŒã¬ãã«ïŒ X以äž" context.level> =åŒæ°['X']ãto_i çµãã
å¶éã®åã¿ã€ãã§ã¯ãååïŒdeck_sum_betweenïŒããïŒ NãšïŒ Mã®éã®ã«ãŒãã¬ãã«ã®åèšããšãã説æãèšå®ããŸãããã®èª¬æããããã©ã¡ãŒã¿ãŒã«åºã¥ããŠãç¹å®ã®å¶éã®èª¬æãååŸãããŸãã ãããŠãã¡ããããã¬ãŒã€ãŒãŸãã¯ä»ã®ãªããžã§ã¯ããå¶çŽã«é©åããå Žåã«trueãè¿ãå¶çŽã®å®è£ ã ãããã£ãŠãã·ã¹ãã ã¯æ®éçã§ããããŠãŒã¶ãŒã§ã¯ãªãã³ã³ããã¹ãã§ãã
çµæãšããŠãdeck_sum_betweenïŒN => 10ãM => 20ïŒã®ããã«å¶éãèšè¿°ãããããªããžã§ã¯ãã®ããŸããŸãªããããã£ã«ååãšãã©ã¡ãŒã¿ãŒãä¿åãããã§ããŸãã
èšèªã¯å¶çŽã®è«çåŒã§ã
ã²ãŒã éçºã§ã¯ãå€ãã®å Žåãã¢ã«ãŽãªãºã ã®åœ¢æã«åºã¥ããããã€ãã®ã«ãŒã«ãããŒã¿ããŒã¹ãªã©ã«åçã«ä¿åããå¿ èŠããããããã²ãŒã ã¢ã«ãŽãªãºã ã¯ç®¡çãã©ãŒã ããæåéãå€æŽã§ããŸãã ãã®äŸãšæ¬¡ã®äŸã§ã¯ããã®ãããª2ã€ã®èšèªã«ã€ããŠèª¬æããŸãã
åºæ¬çãªå¶çŽã®ãªã¹ãã§å®è£ ã§ããåçŽãªå¶çŽã§ã¯ãªããããè€éãªè«çåŒãå¿ èŠãªå ŽåããããŸãã
äŸïŒãã¬ã€ã€ãŒã¬ãã«> 10 ANDããããµã€ãº<= 8 ANDã«ãŒãïŒã¯ã©ã³1ã2ã3ã®ã«ãŒããŸãã¯ã¯ã©ã³4ã5ã®ã«ãŒãïŒã
ãããèšå®ããåŒèšèªãäœæãããŠããŸãïŒããã§ã¯ãåã®ã»ã¯ã·ã§ã³ãšã¯å°ãç°ãªãçš®é¡ã®åºæ¬çãªå¶éã䜿çšãããŠããŸãïŒã
ïŒããã³user_level_geïŒ12ïŒ deck_size_leïŒ8ïŒ ïŒãŸãã¯deck_has_only_clansïŒ1,2,3ïŒ deck_has_only_clansïŒ4,5,6ïŒïŒïŒ
Iã®å€§èŠæš¡ãªãªã¹ããå«ãå¶éã®ãªã¹ãã§ããããã䟿å©ã«ããããã«ãå°ãlispã¹ã¿ã€ã«ã䜿çšããŸããã
次ã«ããã®è¡ãéšå±ã¢ãã«ïŒroom.restrictions_stringïŒã«ä¿åããŸãã parsimæååã®å¶éãèšç®ããå¿ èŠããããšãã«ããã¹ãŠã®åºæ¬çãªå¶éãšå šäœã®çµæãèšç®ããŠãã¯ã©ã€ã¢ã³ãã«æž¡ããŸãã ãã¬ãŒã€ãŒã¯ãå¿ èŠãªæ¡ä»¶ãšãåæ Œããªãã£ãæ¡ä»¶ã確èªããŸãã
ããŒã¹ã¿ãŒã«ãŒã«èšè¿°èšèª
ããŒã¹ã¿ãŒã¯ãåéå¯èœãªã«ãŒãã²ãŒã ã§è²©å£²ãããäžé£ã®ã«ãŒãã§ãç¹å®ã®ã«ãŒã«ã«åŸã£ãŠã©ã³ãã ãªã«ãŒããããã€ãå«ãŸããŠããŸãã ããšãã°ã沌å°äœæ°ã®5ã€ã®äžèŠæš¡ããããš1ã€ã®è¯å¥œãªãããã
ã«ãŒããçæããããã®åã«ãŒã«ã¯ãããã¹ãã§èª¬æã§ããŸãã
åžå°æ§ïŒ1ïŒ-äžæ£ãªã«ãŒãïŒçªå·ã¯ã«ãŒã«ã«èšå®ãããŠããŸãã詳现ã¯åŸã»ã©ïŒ
åžå°æ§ïŒ1ïŒ|æ°æïŒ6,7,8ïŒ-æ°æ6,7,8ã®äžè¯ã«ãŒã1æã ã|ã ããã§ã¯ãè«çORã§ã¯ãªããUNIXãã€ãã©ã€ã³ã象城ããŠããŸãã
確çã§ã«ãŒã«ãå¯èœã§ãïŒ
ã¯ã©ã³ïŒ1,2,3ïŒ|æåŸ ïŒ1,60,2,38,3,2ïŒ-ã¯ã©ã³1ã2ãŸãã¯3ã®ã«ãŒãã 60ïŒ ã®ç¢ºçã§-æªãã38ïŒ ã®ç¢ºçã§-äžã3ïŒ ã®ç¢ºçã§-è¯ãã
åã«ãŒã«ã¯ã次ã®ãããªActiveRecordã¹ã³ãŒãã¡ã«ããºã ã«åºã¥ããŠå®è£ ãããŸãã
def rule_clansïŒã¹ã³ãŒããIDïŒ scope.scoped_by_clan_idïŒidsïŒ çµãã def rule_expectanceïŒã¹ã³ãŒãããã©ã¡ãŒã¿ãŒïŒ scope.scoped_by_rarityïŒExpectance.for_expectanceïŒããã·ã¥[* params.mapïŒïŒïŒto_iïŒ]ïŒïŒïŒ çµãã
ãšããã§ãããã§ããèšèªãæ¡åŒµãã説æãããå°ãç°¡æœã«ããããšãã§ããŸããã
ã«ãŒã«ã¯çµã¿åããããŠåæžãããŸãïŒ
def generate_card_original rules_scope = rules.reduceïŒã«ãŒã::ãªãªãžãã«ïŒdo | scopeãrule | rule.add_scopeïŒã¹ã³ãŒãïŒ çµãã rules_scope.randomly.findïŒïŒæåïŒ çµãã
ãã®çµæãã«ãŒã«ã®è€éãã«é¢ä¿ãªããã«ãŒãããšã«1ã€ã®ãªã¯ãšã¹ããåãåããŸãã
åé¡ã¯ãããã«ãŒã«ã«åŸã£ãŠ5æã®ã«ãŒããçæããå¥ã®ã«ãŒã«ã«åŸã£ãŠ2æã®ã«ãŒããçæããæ¹æ³ã§ãã ããã€ãã®ãªãã·ã§ã³ããããŸããããã®ã¯ã©ã¹ã®Booster has_manyãžã§ãã¬ãŒã¿ãŒã䜿çšããŸããã Generatorã¯ã©ã¹ã®ãªããžã§ã¯ãã«ã¯ãã«ãŒãã®æ°ãšãåã«ãŒããçæãããã«ãŒã«ãæ ŒçŽãããŸãã ããããããŒã¹èšèªãè€éã«ãããã¹ãŠã®ããŒã¹ã¿ãŒã«ãŒã«ã1è¡ã§æžãçããããšãã§ããŸãã
5 [åžå°æ§ïŒ1,2ïŒ]ã2 [ã¯ã©ã³ïŒ1,2ïŒ|æåŸ ïŒ1,60,2,40ïŒ]
ãããã«
ç§ã¯æ¥åžžã®ç·Žç¿ã§LOPã䜿çšããäŸã瀺ããŸããã å€ãã®å ŽåãDSLãå®çŸããããšãªã䜿çšããŸãïŒXMLãæå®ããã€ã³ã¿ãŒãã§ã€ã¹ãªã©ïŒã ãã ããDSLãäœæããéçºè ã¯ããå°æ°ã§ãã ãã®èšäºãããªãã«åé¡ã®è©³çŽ°ãªç 究ãä¿ãããšãé¡ã£ãŠããŸãã