Skip to content

Instantly share code, notes, and snippets.

@parrot-studio
Last active August 29, 2015 14:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save parrot-studio/b937179bff3d61f69df5 to your computer and use it in GitHub Desktop.
Save parrot-studio/b937179bff3d61f69df5 to your computer and use it in GitHub Desktop.
react.jsをお試し中
searchArcanas = (query, path, component, callback) ->
component.setState(showError: false)
$("#loading-modal").modal('show')
query ?= {}
query.ver = $("#data-ver").val()
url = $("#app-path").val() + path
callbacks =
done: (as) ->
callback(as, component)
$("#loading-modal").modal('hide')
fail: ->
$("#loading-modal").modal('hide')
component.setState(showError: true)
switch path
when 'ptm'
Searcher.searchMembers(query, url, callbacks)
when 'codes'
Searcher.searchCodes(query, url, callbacks)
else
Searcher.search(query, url, callbacks)
Row = ReactBootstrap.Row
Col = ReactBootstrap.Col
Well = ReactBootstrap.Well
Alert = ReactBootstrap.Alert
Button = ReactBootstrap.Button
Badge = ReactBootstrap.Badge
Glyphicon = ReactBootstrap.Glyphicon
Label = ReactBootstrap.Label
HeaderArea = React.createClass
render: ->
`<div className="header">
<h1>
Get our light!
<span className="hidden-sm hidden-md hidden-lg"><br /></span>
<small className="text-muted lead">チェンクロ パーティーシミュレーター</small>
</h1>
</div>`
ErrorArea = React.createClass
render: ->
return null unless @props.show
url = location.href
`<Row>
<Col xs={12} md={12} sm={12}>
<Alert bsStyle="danger">
<p>
<strong>データの取得に失敗しました。</strong>
<a href={url} className="alert-link">リロードする</a>か、もう一度検索してください。
</p>
</Alert>
</Col>
</Row>`
ArcanaSkill = React.createClass
renderEffect: (ef, i) ->
sd = ""
sd += "=> " if i > 0
sd += Skill.typeNameFor(ef.category)
sd += " - "
sd += Skill.subnameFor(ef.category, ef.subcategory)
if Skill.subeffectForEffect(ef).length > 0
se = []
for e in Skill.subeffectForEffect(ef)
se.push Skill.effectNameFor(ef.category, e)
sd += " ( + #{se.join(' / ')} )"
`<li key={i}>{sd}</li>`
render: ->
sk = @props.skill
return `<span>(不明)</span>` unless sk
efs = []
for ef, i in sk.effects
efs.push @renderEffect(ef, i)
`<div>
{sk.name} ({sk.cost})<br />
<ul className='small list-unstyled ability-detail'>
{efs}
</ul>
</div>`
ArcanaAbility = React.createClass
render: ->
ab = @props.ability
return `<span>なし</span>` unless ab
efs = []
for e, i in ab.effects
efs.push `<li key={i}>{Ability.conditionNameFor(e.conditionType)} - {Ability.effectNameFor(e.effectType)}</li>`
`<div>
{ab.name}
<ul className='small list-unstyled ability-detail'>
{efs}
</ul>
</div>`
ArcanaDetail = React.createClass
render: ->
a = @props.arcana
return null unless a
cl = "#{a.jobClass} arcana"
`<div className={cl}>
<ArcanaHeader arcana={a} />
<div className='arcana-view-body'>
<h4 className='arcana-name'>
<span className='text-muted'>{a.title}</span>
<strong>{a.name}</strong>
</h4>
<Row>
<div className='col-xs-12 hidden-sm hidden-md hidden-lg'>
<p className='pull-right'>
<input type='checkbox' className='fav' data-job-code={a.jobCode} />
</p>
</div>
<Col xs={12} sm={4} md={4}>
<dl className='small arcana-view-detail'>
<dt>職業</dt>
<dd>{a.jobDetail}</dd>
<dt>ATK / HP</dt>
<dd>{a.maxAtk} / {a.maxHp}<br />( {a.limitAtk} / {a.limitHp} )</dd>
<dt>武器タイプ</dt>
<dd>{a.weaponName}</dd>
<dt>所属</dt>
<dd>{Arcana.unionNameFor(a.union)}</dd>
<dt>声優</dt>
<dd>{a.voiceActor}</dd>
<dt>イラストレーター</dt>
<dd>{a.illustrator}</dd>
<dt>入手先</dt>
<dd>{Arcana.sourceCategoryNameFor(a.sourceCategory)} - {Arcana.sourceNameFor(a.sourceCategory, a.source)}</dd>
</dl>
</Col>
<Col xs={12} sm={8} md={8}>
<dl className='small arcana-view-detail'>
<dt>スキル</dt>
<dd><ArcanaSkill skill={a.skill} /></dd>
<dt>アビリティ1</dt>
<dd><ArcanaAbility ability={a.firstAbility} /></dd>
<dt>アビリティ2</dt>
<dd><ArcanaAbility ability={a.secondAbility} /></dd>
<dt>絆アビリティ</dt>
<dd><ArcanaAbility ability={a.chainAbility} /></dd>
</dl>
</Col>
<Col xs={12} sm={12} md={12}>
<p className='pull-left'>
<Button>Wikiで確認</Button>
</p>
<p className='pull-right hidden-xs'>
<input type='checkbox' className='fav' data-job-code={a.jobCode} />
</p>
</Col>
</Row>
</div>
</div>`
MemberArcanaHeader = React.createClass
render: ->
m = @props.member
return null unless m
a = m.arcana
return null unless a
cl = "arcana-title small #{a.jobClass}-title"
cost = a.cost
cost += " + #{m.chainArcana.chainCost}" if m.chainArcana
`<div className={cl}>
{a.jobNameShort} : {a.rarityStars} <Badge className='pull-right'>{cost}</Badge>
</div>`
ArcanaHeader = React.createClass
render: ->
a = @props.arcana
return null unless a
cl = "arcana-title small #{a.jobClass}-title"
cost = "#{a.cost} ( #{a.chainCost} )"
`<div className={cl}>
{a.jobNameShort} : {a.rarityStars} <Badge className='pull-right'>{cost}</Badge>
</div>`
ArcanaInfoButton = React.createClass
viewModalShow: ->
a = @props.arcana
React.render `<ArcanaDetail arcana={a} />`, document.getElementById('view-detail')
# TODO 管理の方法を検討
$(".fav").bootstrapSwitch({
state: false # TODO
size: 'mini'
onColor: 'success'
labelText: 'お気に入り'
onSwitchChange: (e, state) ->
target = $(e.target)
# TODO 実装
#toggleFavoriteArcana(target.data('jobCode'), state)
})
render: ->
_show = @viewModalShow
`<Button bsSize="xsmall"
className="pull-right"
data-toggle='modal'
data-target='#view-modal'
onClick={_show}>Info</Button>`
ChainedArcana = React.createClass
renderWithLink: ->
m = @props.member
return null unless m
c = m.chainArcana
return null unless c
abn = if m.canUseChainAbility()
`<span className='chained-ability'>{c.chainAbility.name}</span>`
else
`<s>{c.chainAbility.name}</s>`
_ubc = m.unbindChain
`<span>
<button className='close' onClick={_ubc}>&times;</button>
<a>{c.name}</a>
<span> / </span>
{abn}
</span>`
renderNoLink: ->
m = @props.member
return null unless m
c = m.chainArcana
return null unless c
abn = if m.canUseChainAbility()
`<span>{c.chainAbility.name}</span>`
else
`<s>{c.chainAbility.name}</s>`
`<span>{c.name} / {abn}</span>`
render: ->
if @props.noLink
@renderNoLink()
else
@renderWithLink()
ChainedArcanaForSelect = React.createClass
render: ->
a = @props.arcana
c = @props.chain
return null unless (a && c)
return `<span>({a.chainAbility.name})</span>` if a.jobCode is c.jobCode
abn = if Arcana.canUseChainAbility(a, c)
`<span className='chained-ability'>{c.chainAbility.name}</span>`
else
`<s>{c.chainAbility.name}</s>`
`<span>
<span className='chained-ability'>{c.name}</span>
<span> / </span>
{abn}
</span>`
ArcanaName = React.createClass
render: ->
a = @props.arcana
return null unless a
button = (if @props.noInfo then null else `<ArcanaInfoButton arcana={a} />`)
`<p>
<small>
{button}
<span className='text-muted small'>{a.title}</span><br />
<strong>{a.name}</strong>
</small>
</p>`
ArcanaSummaryData = React.createClass
render: ->
a = @props.arcana
m = @props.member
a = m?.arcana unless a
return null unless a
ca = @props.chain
abs1 = (if a.firstAbility.name != '' then a.firstAbility.name else 'なし')
abs2 = (if a.secondAbility.name != '' then a.secondAbility.name else 'なし')
chain = if m
if m.chainArcana
nl = @props.noLink
`<ChainedArcana member={m} noLink={nl} />`
else
`<span>({a.chainAbility.name})</span>`
else if ca
`<ChainedArcanaForSelect arcana={a} chain={ca} />`
else
`<span>{a.chainAbility.name}</span>`
`<div>
<small>
<ul className='small text-muted list-unstyled summary-detail'>
<li>{a.maxAtk} / {a.maxHp}</li>
<li>{a.skill.name} ({a.skill.cost})</li>
<li>{abs1}<br />{abs2}</li>
<li className='chain-ability-name'>{chain}</li>
</ul>
</small>
</div>`
MemberArcanaSummaryBody = React.createClass
render: ->
m = @props.member
return null unless (m && m.arcana)
`<div className='arcana-summary'>
<ArcanaName arcana={m.arcana} />
<ArcanaSummaryData member={m} />
</div>`
MemberArcanaSummary = React.createClass
componentDidMount: ->
d = $(@getDOMNode())
d.draggable(
connectToSortable: false
containment: false
helper: 'clone'
opacity: 0.7
zIndex: 10000
start: ->
document.getElementById('search-area').className = 'hide'
React.render `<HelpArea />`, document.getElementById('help-area')
stop: ->
document.getElementById('search-area').className = ''
React.render `<div />`, document.getElementById('help-area')
)
render: ->
m = @props.member
a = m?.arcana
cl = "summary-size arcana "
cl += (if a then a.jobClass else "none")
`<div className="member-character" data-area-id={m.areaId}>
<div className={cl}>
<MemberArcanaHeader member={m} />
<MemberArcanaSummaryBody member={m} />
</div>
</div>`
ChainSelectModal = React.createClass
setChainArcana: ->
m = @props.member
rm = @props.replaceMember
ca = (if rm then rm.arcana else @props.replaceArcana)
m.setArcana(m.arcana, ca)
$('#select-modal').modal('hide')
replaceMember: ->
m = @props.member
rm = @props.replaceMember
a = (if rm then rm.arcana else @props.replaceArcana)
c = (if rm then rm.chainArcana else null)
m.setArcana(a, c)
$('#select-modal').modal('hide')
renderChainedArcana: ->
a = @props.member.arcana
rm = @props.replaceMember
ca = (if rm then rm.arcana else @props.replaceArcana)
cl = "summary-size arcana #{a.jobClass}"
mcl = "arcana-title small #{a.jobClass}-title"
cost = "#{a.cost} + #{ca.chainCost}"
`<div className={cl}>
<div className={mcl}>
{a.jobNameShort} : {a.rarityStars} <Badge className='pull-right'>{cost}</Badge>
</div>
<div className='arcana-summary'>
<ArcanaName arcana={a} noInfo={true} />
<ArcanaSummaryData arcana={a} chain={ca} />
</div>
</div>`
renderChainState: ->
a = @props.member.arcana
rm = @props.replaceMember
ca = (if rm then rm.arcana else @props.replaceArcana)
ab = if Arcana.canUseChainAbility(a, ca)
`<Label bsStyle="success">絆アビリティ使用可能</Label>`
else
`<Label bsStyle="danger">絆アビリティ使用不可</Label>`
union = if a.union == ca.union
`<Label bsStyle="success">所属ボーナスあり</Label>`
else
`<Label bsStyle="warning">所属ボーナスなし</Label>`
`<div>{ab} {union}</div>`
renderReplaced: ->
rm = @props.replaceMember
ra = @props.replaceArcana
if rm
@renderReplacedWithMember(rm)
else
@renderReplacedWithArcana(ra)
renderReplacedWithMember: (m) ->
return null unless m
a = m.arcana
return null unless a
cl = "summary-size arcana #{a.jobClass}"
mcl = "arcana-title small #{a.jobClass}-title"
`<div className={cl}>
<MemberArcanaHeader member={m} />
<div className='arcana-summary'>
<ArcanaName arcana={a} noInfo={true} />
<ArcanaSummaryData member={m} noLink={true} />
</div>
</div>`
renderReplacedWithArcana: (a) ->
return null unless a
cl = "summary-size arcana #{a.jobClass}"
mcl = "arcana-title small #{a.jobClass}-title"
`<div className={cl}>
<div className={mcl}>
{a.jobNameShort} : {a.rarityStars} <Badge className='pull-right'>{a.cost}</Badge>
</div>
<div className='arcana-summary'>
<ArcanaName arcana={a} noInfo={true} />
<ArcanaSummaryData arcana={a} chain={a} />
</div>
</div>`
render: ->
renderChained = @renderChainedArcana()
renderReplaced = @renderReplaced()
renderChainState = @renderChainState()
_sc = @setChainArcana
_rm = @replaceMember
`<div className="modal-dialog">
<div className="modal-content">
<div className="modal-header">
<button className="close" data-dismiss="modal"><span aria-hidden="true">&times; Close</span></button>
<h2 className="modal-title">セット先選択</h2>
</div>
<div className="modal-body">
<Row>
<Col sm={6} md={6}>
<Button bsStyle="primary" onClick={_sc}>
<Glyphicon glyph="link" /> 絆として追加する
</Button>
<p className="clearfix"></p>
<label>絆設定後</label>
<Col sm={10} md={10}>
{renderChained}
</Col>
{renderChainState}
</Col>
<Col sm={6} md={6}>
<Button bsStyle="info" onClick={_rm}>
<Glyphicon glyph="user" /> メンバーとして置き換える
</Button>
<p className="clearfix"></p>
<label>置き換え後</label>
<Col sm={10} md={10}>
{renderReplaced}
</Col>
</Col>
</Row>
</div>
<div className="modal-footer">
<Button data-dismiss="modal">
<Glyphicon glyph="remove" /> セットしないで閉じる
</Button>
</div>
</div>
</div>`
MemberArcana = React.createClass
replaceMemberFromMember: (omem, rmem) ->
return if omem.areaId is rmem.areaId
unless omem.arcana
omem.setArcana(rmem.arcana, rmem.chainArcana)
rmem.deleteMember() unless omem.areaId is 'friend'
else
React.render `<ChainSelectModal member={omem} replaceMember={rmem} />`, document.getElementById('select-modal')
$("#select-modal").modal("show")
replaceMemberFromTarget: (omem, ta) ->
unless omem.arcana
omem.setArcana(ta)
return
React.render `<ChainSelectModal member={omem} replaceArcana={ta} />`, document.getElementById('select-modal')
$("#select-modal").modal("show")
handleDropedArcana: (mem, drag) ->
areaId = drag.data("areaId") # from member
code = drag.data("jobCode") # from target
if areaId
dmem = mem.members.memberForId(areaId)
@replaceMemberFromMember(mem, dmem)
else if code
a = Searcher.forCode(code)
@replaceMemberFromTarget(mem, a)
componentDidMount: ->
d = $(@getDOMNode())
d.droppable(
drop: (e, ui) =>
e.preventDefault()
@handleDropedArcana(@props.member, ui.draggable)
)
render: ->
headers =
mem1: "Leader"
mem2: "2nd"
mem3: "3rd"
mem4: "4th"
sub1: "Sub1"
sub2: "Sub2"
friend: "Friend"
m = @props.member
h = headers[m.areaId]
_dm = m.deleteMember
delbtn = if m.arcana
`<button className="close" aria-hidden="true" onClick={_dm}>&times;</button>`
else
null
`<li className="col-xs-6 col-sm-3 col-md-3">
{delbtn}
<label className="member-label">{h}</label>
<MemberArcanaSummary member={m} />
</li>`
TotalCost = React.createClass
render: ->
cost = (@props.cost || 0)
`<li className="col-xs-6 col-sm-3 col-md-3">
<p className="text-center">
<label>Total Cost</label><br />
<span className="cost">{cost}</span>
</p>
</li>`
MemberAreaHeader = React.createClass
render: ->
`<Row>
<Col md={12} sm={12} className="hidden-xs">
<h2>パーティー編集</h2>
</Col>
</Row>`
MemberArea = React.createClass
render: ->
members = @props.members
return null unless members
mems = []
members.eachMembers (k, m) =>
mems.push `<MemberArcana key={k} member={m} />`
`<Well bsSize="small">
<MemberAreaHeader />
<Row>
<Col xs={12} sm={12} md={12} className="member-list">
<ul className="list-inline">
{mems}
<TotalCost cost={members.cost} />
</ul>
</Col>
</Row>
</Well>`
EditButton = React.createClass
viewShareModal: ->
mems = @props.members
return null unless mems
console.log document.getElementById('app-path')
appUrl = document.getElementById('app-path').value
url = appUrl + mems.createCode()
document.getElementById('ptm-code').value = url
twitterUrl = "https://twitter.com/intent/tweet"
twitterUrl += "?text=#{encodeURIComponent('チェンクロ パーティーシミュレーター ' + url)}"
twitterUrl += "&hashtags=ccpts"
document.getElementById('twitter-share').href = twitterUrl
render: ->
mems = @props.members
return null unless mems
edit = if mems.editMode
`<Button bsStyle="primary" className="act-btn">
<Glyphicon glyph="check" /> 編集終了
</Button>`
else
`<Button bsStyle="primary" className="act-btn">
<Glyphicon glyph="edit" /> 編集する
</Button>`
_vsm = @viewShareModal
`<Row>
<Col sm={12} md={12}>
{edit}
<Button
bsStyle="info"
className="act-btn"
data-toggle="modal"
data-target="#share-ptm-modal"
onClick={_vsm}>
<Glyphicon glyph="cloud" /> 共有
</Button>
<Button bsStyle="link" className="act-btn" data-toggle="modal" data-target="#help-modal">
使い方
</Button>
</Col>
</Row>`
EditArea = React.createClass
render: ->
mems = @props.members
`<div>
<EditButton members={mems} />
<MemberArea members={mems} />
</div>`
TargetArcanaBody = React.createClass
render: ->
a = @props.arcana
return null unless a
`<div className='arcana-summary'>
<ArcanaName arcana={a} />
<ArcanaSummaryData arcana={a} />
</div>`
TargetArcana = React.createClass
componentDidMount: ->
return unless @props.arcana
d = $(@getDOMNode())
d.draggable(
connectToSortable: false
containment: false
helper: 'clone'
opacity: 0.7
zIndex: 10000
start: ->
document.getElementById('search-area').className = 'hide'
React.render `<HelpArea />`, document.getElementById('help-area')
stop: ->
document.getElementById('search-area').className = ''
React.render `<div />`, document.getElementById('help-area')
)
render: ->
a = @props.arcana
cl = "summary-size arcana "
cl += (if a then a.jobClass else "none")
code = (if a then a.jobCode else null)
`<div className={cl} data-job-code={code}>
<ArcanaHeader arcana={a} />
<TargetArcanaBody arcana={a} />
</div>`
TargetArcanas = React.createClass
render: ->
results = @props.results
return null unless results
ts = []
for a, i in results.targets()
ts.push `<li className='listed-character col-sm-3 col-md-3 col-xs-6' key={a.jobCode}>
<TargetArcana arcana={a} />
</li>`
`<div>
<ul className="list-inline">
{ts}
</ul>
</div>`
PageLink = React.createClass
jumpPage: (e)->
results = @props.results
return null unless results
page = e.target.dataset.page
results.jumpPage(page)
renderPage: (p, i) ->
return null unless p
results = @props.results
return null unless results
page = results.page()
_jp = @jumpPage
if p is page
`<li key={i} className="active"><span>{p}</span></li>`
else if p is '..'
`<li key={i} className="disable"><span>{p}</span></li>`
else
`<li key={i}><span onClick={_jp} data-page={p}>{p}</span></li>`
renderPrevPage: ->
results = @props.results
return null unless results
if results.hasPrevPage()
_pp = results.prevPage
`<li><span onClick={_pp}>&larr;</span></li>`
else
`<li className="disabled"><span>&larr;</span></li>`
renderNextPage: ->
results = @props.results
return null unless results
if results.hasNextPage()
_np = results.nextPage
`<li><span onClick={_np}>&rarr;</span></li>`
else
`<li className="disabled"><span>&rarr;</span></li>`
render: ->
results = @props.results
return null unless results
pager = results.pager
return null unless pager
isPhone = @props.isPhone
pcl = "pagination"
pcl += " pagination-sm" if isPhone
prev = @renderPrevPage()
next = @renderNextPage()
plist = if isPhone
results.paginationList(3, 1)
else
results.paginationList(5, 2)
pl = []
for p, i in plist
pl.push @renderPage(p, i)
`<nav className="text-center">
<ul className={pcl}>
{prev}
{pl}
{next}
</ul>
</nav>`
HelpArea = React.createClass
render: ->
`<Row>
<Col sm={12} md={12}>
<Alert bsStyle="warning" className="small">
<ul className="list-unstyled">
<li>空いたところにドロップ -> パーティーメンバーとしてセット</li>
<li>すでに登録されたところにドロップ -> 「置き換え」か「絆」か選択</li>
</ul>
</Alert>
</Col>
</Row>`
SearchArea = React.createClass
render: ->
results = @props.results
return null unless results
pager = results.pager
count = if pager.size > 0
"(#{pager.head() + 1} - #{pager.tail() + 1} / #{pager.size}件)"
else
"(0件)"
# TODO 検索にあった文字列
str = "最新"
`<Row>
<Col sm={12} md={12}>
<div className="bg-info small text-muted">
<div className="btn-group pull-right">
<Button className="dropdown-toggle" data-toggle="dropdown">
<Glyphicon glyph="menu-hamburger" /> 履歴 <span className="caret"></span>
</Button>
<ul className="dropdown-menu" role="menu">
<li><a><Glyphicon glyph="refresh" /> 最新のアルカナ</a></li>
<li><a><Glyphicon glyph="star" /> お気に入り</a></li>
<li><a><Glyphicon glyph="export" /> 最後に作ったパーティー構成</a></li>
<li className="divider"></li>
<li role="presentation" className="dropdown-header">検索履歴</li>
</ul>
</div>
<Button bsStyle="primary" data-toggle="modal" data-target="#search-modal">
<Glyphicon glyph="search" /> 検索
</Button>
表示中:{str} <span className="pager-count">{count}</span>
</div>
<div>
<span className="help-block small">アルカナをドラッグ -> 上のパーティーエリアでドロップ</span>
</div>
</Col>
</Row>`
TargetArea = React.createClass
render: ->
results = @props.results
`<div>
<div id="help-area"></div>
<div id="search-area"><SearchArea results={results} /></div>
<TargetArcanas results={results} />
<PageLink results={results} />
</div>`
class SearchResult
constructor: (view, rs) ->
psize = (view.state.pagerSize || 8)
@pager = new Pager(rs, psize)
@component = view
@search: (query, view) ->
unless query
result = new SearchResult(view, [])
result.updateState()
return
searchArcanas query, 'arcanas', view, (as, component) ->
result = new SearchResult(component, as)
result.updateState()
updateState: ->
@component.setState(results: @)
targets: ->
@pager.get() || []
page: ->
@pager.page
hasPrevPage: ->
@pager.hasPrevPage()
prevPage: =>
@pager.prevPage()
@updateState()
hasNextPage: ->
@pager.hasNextPage()
nextPage: =>
@pager.nextPage()
@updateState()
jumpPage: (n) ->
@pager.jumpPage(n)
@updateState()
paginationList: (body, edge) ->
return [] unless @pager
return [1 .. @pager.maxPage] if (@pager.maxPage <= (body + edge * 2 + 2))
switch
when @pager.page <= (edge + (body+1)/2)
li = [1 .. (body + edge)]
li.push '..'
li = li.concat [(@pager.maxPage - edge + 1) .. @pager.maxPage]
li
when @pager.page >= (@pager.maxPage - (edge + (body+1)/2) + 1)
li = [1 .. edge]
li.push '..'
li = li.concat [(@pager.maxPage-(body + edge)+1) .. @pager.maxPage]
li
else
li = [1 .. edge]
li.push '..'
li = li.concat [(@pager.page - edge) .. (@pager.page + edge)]
li.push '..'
li = li.concat [(@pager.maxPage - edge + 1) .. @pager.maxPage]
li
class Member
constructor: (aid, mems, a) ->
@areaId = aid
@members = mems
@arcana = a
@chainArcana = null
chainedCost: ->
return 0 unless @arcana
c = @arcana.cost
return c unless @chainArcana
(c + @chainArcana.chainCost)
canUseChainAbility: ->
return false unless (@arcana && @chainArcana)
return false unless @arcana.jobType == @chainArcana.jobType
return false if @arcana.name == @chainArcana.name
true
deleteMember: =>
@arcana = null
@chainArcana = null
@members.updateState()
unbindChain: =>
@chainArcana = null
@members.updateState()
setArcana: (a, c) ->
@arcana = a
@chainArcana = c
@members.updateState()
@members.removeDuplicateMember(@)
class Members
defaultMemberCode = 'V2F82F85K51NA38NP28NP24NNNNN'
memberKeys = ['mem1', 'mem2', 'mem3', 'mem4', 'sub1', 'sub2', 'friend']
ver = document.getElementById('pt-ver').value
constructor: (component) ->
@ptm = {}
@component = component
@editMode = true
@initMembers: (view, code) ->
c = code || defaultMemberCode
query = ptm: c
searchArcanas query, 'ptm', view, (as, component) ->
mems = new Members(component)
for k in memberKeys
ma = as[k]
mc = as[k + 'c']
m = new Member(k, mems, ma)
if ma && mc
m.chainArcana = mc
mems.addMember(m)
mems.updateState()
memberForId: (aid) ->
@ptm[aid]
eachMembers: (f) ->
for k in memberKeys
f(k, @ptm[k])
updateState: ->
@cost = calcTotalCost(@ptm)
@component.setState(members: @)
addMember: (m) ->
return unless m
@ptm[m.areaId] = m
updateMember: (m) ->
return unless m
@addMember(m)
@updateState()
removeDuplicateMember: (org) ->
return unless org
aid = org.areaId
return if aid is 'friend'
oa = org.arcana
return unless oa
n1 = oa.name
n2 = org.chainArcana?.name || ''
@eachMembers (k, m) ->
return if k is 'friend'
return if k is aid
a = m.arcana
return unless a
if (a.name is n1 || a.name is n2)
m.deleteMember()
else if m.chainArcana
cn = m.chainArcana.name
if (cn is n1 || cn is n2)
m.unbindChain()
changeEditMode: (mode) ->
@editMode = mode
createCode: ->
header = "V#{ver}"
code = ''
@eachMembers (k, m) ->
if m?.arcana
code += m.arcana.jobCode
code += (if m.chainArcana then m.chainArcana.jobCode else 'N')
else
code += 'NN'
if (/^N+$/).test(code) then '' else (header + code)
# private
calcTotalCost = (ptm)->
cost = 0
for k in memberKeys
continue if k is 'friend'
m = ptm[k]
cost += m.chainedCost() if m
cost
PtEditView = React.createClass
getInitialState: ->
members: null
results: null
showError: false
pagerSize: 8
componentDidMount: ->
Members.initMembers(@)
SearchResult.search({recently: 24}, @)
render: ->
state = @state
`<div>
<HeaderArea />
<ErrorArea show={state.showError} />
<EditArea members={state.members} />
<TargetArea results={state.results} />
</div>`
React.render `<PtEditView />`, document.getElementById('ptedit')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment