MediaWiki:PartySimulator.js

From CoraTO Wiki - Official Wiki
Jump to navigation Jump to search

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
(function(){
var types=["Power","Magic","Sense","Charm"];
var genders=["Girl","Boy"];
var BOOSTS={
  2:{normal:[20,20],beginner:[30,30],type:[20,20],royal:[30,50],special:[30,50],fixed:null},
  3:{normal:[30,30],beginner:[40,50],type:[40,40],royal:[50,50],special:[50,50],fixed:null},
  4:{normal:[30,30],beginner:[40,50],type:[40,40],royal:[50,50],special:[50,50],fixed:null},
  5:{normal:[40,50],beginner:[60,80],type:[70,100],royal:[100,150],special:[100,150],fixed:null},
  6:{normal:[50,80],beginner:[80,100],type:[100,150],royal:[150,200],special:[150,200],fixed:null}
};
var state;

function q(s,c){return(c||document).querySelector(s)}
function ce(t,c){var e=document.createElement(t);if(c)Object.assign(e,c);return e}
function on(el,ev,fn){if(el){el.addEventListener(ev,fn)}}

function init(){
  var countInput=q('#sim-member-count');
  var countValue=q('#sim-member-count-value');
  var grid=q('#sim-member-grid');
  var typeName=q('#sim-type-name');
  var typeImg=q('#sim-type-image');
  var expChip=q('#sim-exp-chip');
  var tmChip=q('#sim-tm-chip');
  var rulesBox=q('#sim-rules');
  if(!grid)return;

  var ICON={
    Power:{Girl:'https://mewsie.world/CoraTOWiki/images/d/d3/Bunny_1st_Sprite.png',Boy:'https://mewsie.world/CoraTOWiki/images/0/07/Buffalo_1st_Job.png'},
    Magic:{Girl:'https://mewsie.world/CoraTOWiki/images/0/0f/Sheep_1st_Job.png',Boy:'https://mewsie.world/CoraTOWiki/images/1/14/Dragon_1st_Job.png'},
    Sense:{Girl:'https://mewsie.world/CoraTOWiki/images/1/10/Fox_1st_Job.png',Boy:'https://mewsie.world/CoraTOWiki/images/f/f8/Lion_1st_Job.png'},
    Charm:{Girl:'https://mewsie.world/CoraTOWiki/images/6/65/Cat_1st_Job.png',Boy:'https://mewsie.world/CoraTOWiki/images/d/db/Raccoon_1st_Job.png'}
  };
  function iconSrc(t,g){return ICON[t][g]}

  state={
    count:4,
    members:new Array(6).fill(0).map(function(_,i){
      return{type:types[i%types.length],gender:genders[i%genders.length],level:50}
    })
  };

  function renderChiefOptions(){}

  function renderMembers(){
    grid.innerHTML='';
    for(let i=0;i<state.count;i++){
      let m=state.members[i];
      var card=ce('div',{className:'sim-card'});
      var head=ce('div',{className:'sim-card-header'});
      var imgBox=ce('div',{className:'image-container'});
      let imgEl=ce('img',{alt:m.type+' '+m.gender});
      imgEl.src=iconSrc(m.type,m.gender);
      imgBox.appendChild(imgEl);
      head.appendChild(imgBox);
      var title=ce('div',{className:'sim-card-title'});
      title.textContent='Member '+(i+1);
      head.appendChild(title);
      card.appendChild(head);

      var row1=ce('div');
      row1.className='sim-row';
      var lblType=ce('label');
      lblType.textContent='Type';
      let selType=ce('select',{className:'sim-select'});
      types.forEach(function(t){var o=ce('option',{value:t});o.textContent=t;selType.appendChild(o)});
      selType.value=m.type;
      row1.appendChild(lblType);
      row1.appendChild(selType);
      row1.appendChild(ce('span'));
      card.appendChild(row1);

      var row2=ce('div');
      row2.className='sim-row';
      var lblGen=ce('label');
      lblGen.textContent='Gender';
      let selGen=ce('select',{className:'sim-select'});
      genders.forEach(function(g){var o=ce('option',{value:g});o.textContent=g;selGen.appendChild(o)});
      selGen.value=m.gender;
      row2.appendChild(lblGen);
      row2.appendChild(selGen);
      row2.appendChild(ce('span'));
      card.appendChild(row2);

      var row3=ce('div');
      row3.className='sim-row';
      var lblLvl=ce('label');
      lblLvl.textContent='Level';
      let inpLvl=ce('input',{className:'sim-input',type:'number',min:'1',max:'400',value:String(m.level)});
      row3.appendChild(lblLvl);
      row3.appendChild(inpLvl);
      row3.appendChild(ce('span'));
      card.appendChild(row3);

      grid.appendChild(card);

      on(selType,'change',function(){m.type=this.value;imgEl.src=iconSrc(m.type,m.gender);renderSummary()});
      on(selGen,'change',function(){m.gender=this.value;imgEl.src=iconSrc(m.type,m.gender);renderSummary()});
      on(inpLvl,'input',function(){var v=parseInt(this.value||'0',10);m.level=isNaN(v)?1:Math.max(1,Math.min(400,v));renderSummary()});
  }
  }

  function computeType(){
    var members=state.members.slice(0,state.count);
    var fixed=false;
    for(var i=0;i<members.length;i++){
      for(var j=i+1;j<members.length;j++){
        if(Math.abs(members[i].level-members[j].level)>=100){fixed=true;break}
      }
      if(fixed)break
    }
    if(fixed)return'fixed';
    var allAbove30=members.every(function(m){return m.level>30});
    var hasBeginner=members.some(function(m){return m.level<=30});
    var genderSet=new Set(members.map(function(m){return m.gender}));
    var typeCounts={};
    types.forEach(function(t){typeCounts[t]=0});
    members.forEach(function(m){typeCounts[m.type]++});
    var sameType=types.some(function(t){return typeCounts[t]>=4});
    var hasAll=types.every(function(t){return typeCounts[t]>0});
    var allSameGender=genderSet.size===1&&members.length>=4;
    var hasFourOrMore=members.length>=4;
    if(hasFourOrMore&&allAbove30&&allSameGender)return'special';
    if(hasFourOrMore&&allAbove30&&hasAll&&!allSameGender)return'royal';
    if(hasFourOrMore&&allAbove30&&sameType)return'type';
    if(hasBeginner)return'beginner';
    return'normal'
  }

  function renderSummary(){
    var t=computeType();
    var boosts=BOOSTS[state.count][t];
    var imgMap={normal:'https://mewsie.world/CoraTOWiki/images/d/d1/Normal_Party.png',beginner:'https://mewsie.world/CoraTOWiki/images/b/b0/Beginner_Party.png',type:'https://mewsie.world/CoraTOWiki/images/9/9d/Type_Party.png',royal:'https://mewsie.world/CoraTOWiki/images/b/bb/Royal_Party.png',special:'https://mewsie.world/CoraTOWiki/images/0/0c/Special_Party.png',fixed:'https://mewsie.world/CoraTOWiki/images/a/ae/Fixed_Party.png'};
    typeName.textContent=t.charAt(0).toUpperCase()+t.slice(1);
    typeImg.src=imgMap[t];
    if(boosts){
      expChip.textContent='EXP +'+boosts[0]+'x';
      tmChip.textContent='TM +'+boosts[1]+'x'
    }else{
      expChip.textContent='EXP None';
      tmChip.textContent='TM None'
    }
    var r=[];
    if(t==='fixed')r.push('Fixed: level gap ≥100 between members');
    if(t!=='fixed'){
      var members=state.members.slice(0,state.count);
      var hasBeginner=members.some(function(m){return m.level<=30});
      if(hasBeginner)r.push('Beginner: at least one member ≤30');
      var typeCounts={};
      types.forEach(function(tp){typeCounts[tp]=0});
      members.forEach(function(m){typeCounts[m.type]++});
      if(members.length>=4){
        var allAbove30=members.every(function(m){return m.level>30});
        if(allAbove30){
          if(types.every(function(tp){return typeCounts[tp]>0})&&new Set(members.map(function(m){return m.gender})).size!==1)r.push('Royal: ≥4, one of each type, all >30, mixed gender');
          if(new Set(members.map(function(m){return m.gender})).size===1&&types.some(function(tp){return typeCounts[tp]>=4}))r.push('Special candidate: ≥4 same gender and may meet other conditions');
          if(types.some(function(tp){return typeCounts[tp]>=4}))r.push('Type: ≥4 of same type, all >30')
        }
      }
    }
    rulesBox.innerHTML='';
    r.forEach(function(txt){var d=ce('div',{className:'sim-rule'});d.textContent=txt;d.title=txt;rulesBox.appendChild(d)})
  }

  function update(){
    countValue.textContent=String(state.count);
    renderChiefOptions();
    renderMembers();
    renderSummary();
  }

  on(countInput,'input',function(){state.count=parseInt(countInput.value,10);update()});
  update()
}

if(document.readyState!=='loading'){init()}else{document.addEventListener('DOMContentLoaded',init)}
})();