전투 시뮬레이터 로컬 기능 구현

This commit is contained in:
2018-08-26 17:20:47 +09:00
parent ca57ef17fc
commit 724804efc6
3 changed files with 484 additions and 99 deletions
+132
View File
@@ -0,0 +1,132 @@
//download.js v3.0, by dandavis; 2008-2014. [CCBY2] see http://danml.com/download.html for tests/usage
// v1 landed a FF+Chrome compat way of downloading strings to local un-named files, upgraded to use a hidden frame and optional mime
// v2 added named files via a[download], msSaveBlob, IE (10+) support, and window.URL support for larger+faster saves than dataURLs
// v3 added dataURL and Blob Input, bind-toggle arity, and legacy dataURL fallback was improved with force-download mime and base64 support
// data can be a string, Blob, File, or dataURL
function download(data, strFileName, strMimeType) {
var self = window, // this script is only for browsers anyway...
u = "application/octet-stream", // this default mime also triggers iframe downloads
m = strMimeType || u,
x = data,
D = document,
a = D.createElement("a"),
z = function(a){return String(a);},
B = self.Blob || self.MozBlob || self.WebKitBlob || z,
BB = self.MSBlobBuilder || self.WebKitBlobBuilder || self.BlobBuilder,
fn = strFileName || "download",
blob,
b,
ua,
fr;
//if(typeof B.bind === 'function' ){ B=B.bind(self); }
if(String(this)==="true"){ //reverse arguments, allowing download.bind(true, "text/xml", "export.xml") to act as a callback
x=[x, m];
m=x[0];
x=x[1];
}
//go ahead and download dataURLs right away
if(String(x).match(/^data\:[\w+\-]+\/[\w+\-]+[,;]/)){
return navigator.msSaveBlob ? // IE10 can't do a[download], only Blobs:
navigator.msSaveBlob(d2b(x), fn) :
saver(x) ; // everyone else can save dataURLs un-processed
}//end if dataURL passed?
try{
blob = x instanceof B ?
x :
new B([x], {type: m}) ;
}catch(y){
if(BB){
b = new BB();
b.append([x]);
blob = b.getBlob(m); // the blob
}
}
function d2b(u) {
var p= u.split(/[:;,]/),
t= p[1],
dec= p[2] == "base64" ? atob : decodeURIComponent,
bin= dec(p.pop()),
mx= bin.length,
i= 0,
uia= new Uint8Array(mx);
for(i;i<mx;++i) uia[i]= bin.charCodeAt(i);
return new B([uia], {type: t});
}
function saver(url, winMode){
if ('download' in a) { //html5 A[download]
a.href = url;
a.setAttribute("download", fn);
a.innerHTML = "downloading...";
D.body.appendChild(a);
setTimeout(function() {
a.click();
D.body.removeChild(a);
if(winMode===true){setTimeout(function(){ self.URL.revokeObjectURL(a.href);}, 250 );}
}, 66);
return true;
}
//do iframe dataURL download (old ch+FF):
var f = D.createElement("iframe");
D.body.appendChild(f);
if(!winMode){ // force a mime that will download:
url="data:"+url.replace(/^data:([\w\/\-\+]+)/, u);
}
f.src = url;
setTimeout(function(){ D.body.removeChild(f); }, 333);
}//end saver
if (navigator.msSaveBlob) { // IE10+ : (has Blob, but not a[download] or URL)
return navigator.msSaveBlob(blob, fn);
}
if(self.URL){ // simple fast and modern way using Blob and URL:
saver(self.URL.createObjectURL(blob), true);
}else{
// handle non-Blob()+non-URL browsers:
if(typeof blob === "string" || blob.constructor===z ){
try{
return saver( "data:" + m + ";base64," + self.btoa(blob) );
}catch(y){
return saver( "data:" + m + "," + encodeURIComponent(blob) );
}
}
// Blob but not URL:
fr=new FileReader();
fr.onload=function(e){
saver(this.result);
};
fr.readAsDataURL(blob);
}
return true;
} /* end download() */
+31 -39
View File
@@ -26,6 +26,7 @@ $startYear = $gameStor->getValue('startyear');
<?=WebUtil::printJS('../d_shared/common_path.js')?>
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('../e_lib/download2.js')?>
<?=WebUtil::printJS('js/common.js')?>
<?=WebUtil::printJS('js/battle_simulator.js')?>
</head>
@@ -39,7 +40,11 @@ $startYear = $gameStor->getValue('startyear');
<div class="row">
<div class="col-sm-6">
<div class="input-group">
<input type="number" class="form-control" id="year" aria-describedby="text_year" value="183" min="<?=$startYear?>">
<input type="number" class="form-control" id="year" aria-describedby="text_year" value="<?=$startYear?>" min="<?=$startYear?>" disabled>
<div class="input-group-append">
<span class="input-group-text" id="text_year">년 시작</span>
</div>
<input type="number" class="form-control" id="year" aria-describedby="text_year" value="<?=$startYear+3?>" min="<?=$startYear?>">
<div class="input-group-append">
<span class="input-group-text" id="text_year">년</span>
</div>
@@ -52,12 +57,9 @@ $startYear = $gameStor->getValue('startyear');
<div class="col-sm-6">
<div class="btn-toolbar" role="toolbar">
<div class="btn-group mr-2" role="group">
<button type="button" class="btn btn-primary">저장</button>
<button type="button" class="btn btn-primary">불러오기</button>
</div>
<div class="btn-group mr-2" role="group">
<button type="button" class="btn btn-info export_general">내보내기</button>
<button type="button" class="btn btn-info">가져오기</button>
<button type="button" class="btn btn-info">모두 저장</button>
<input type="file" class="form_load_battle_file" style="display: none;" />
<button type="button" class="btn btn-primary">모두 불러오기</button>
</div>
</div>
</div>
@@ -123,17 +125,14 @@ $startYear = $gameStor->getValue('startyear');
</div>
</div>
</div>
<div class="card mb-2 attacker_form general_form">
<div class="card mb-2 attacker_form general_form" data-general_no='1'>
<div class="card-header">
<div class="float-sm-left" style="line-height:25px;">출병자 설정</div>
<div class="float-sm-right btn-toolbar" role="toolbar">
<div class="btn-group btn-group-sm mr-2" role="group">
<button type="button" class="btn btn-primary">저장</button>
<button type="button" class="btn btn-primary">불러오기</button>
</div>
<div class="btn-group btn-group-sm" role="group">
<button type="button" class="btn btn-info export_general">내보내기</button>
<button type="button" class="btn btn-info">가져오기</button>
<button type="button" class="btn btn-info btn-general-save">저장</button>
<input type="file" class="form_load_general_file" style="display: none;" />
<button type="button" class="btn btn-primary btn-general-load">불러오기</button>
</div>
</div>
</div>
@@ -211,10 +210,8 @@ $startYear = $gameStor->getValue('startyear');
<button type="button" class="btn btn-dark">수비 순서대로 정렬</button>
</div>
<div class="btn-group btn-group-sm mr-2" role="group">
<button type="button" class="btn btn-primary">불러오기</button>
</div>
<div class="btn-group btn-group-sm mr-2" role="group">
<button type="button" class="btn btn-info">가져오기</button>
<input type="file" class="form_load_general_file" style="display: none;" />
<button type="button" class="btn btn-primary btn-general-load-new">불러오기</button>
</div>
<div class="btn-group btn-group-sm" role="group">
<button type="button" class="btn btn-success add-defender">추가</button>
@@ -222,33 +219,31 @@ $startYear = $gameStor->getValue('startyear');
</div>
</div>
</div>
<div class="card mb-2 defender_form general_form">
</div>
<div class="card mb-2 form_sample">
<div class="card-header">
<div class="float-sm-left" style="line-height:25px;">수비자 설정</div>
<div class="float-sm-right btn-toolbar" role="toolbar">
<div class="btn-group btn-group-sm mr-2" role="group">
<button type="button" class="btn btn-primary">저장</button>
<button type="button" class="btn btn-primary">불러오기</button>
</div>
<div class="btn-group btn-group-sm mr-2" role="group">
<button type="button" class="btn btn-info export_general">내보내기</button>
<button type="button" class="btn btn-info">가져오기</button>
<button type="button" class="btn btn-info btn-general-save">저장</button>
<input type="file" class="form_load_general_file" style="display: none;" />
<button type="button" class="btn btn-primary btn-general-load">불러오기</button>
</div>
<div class="btn-group btn-group-sm" role="group">
<button type="button" class="btn btn-warning">복제</button>
<button type="button" class="btn btn-warning copy-defender">복제</button>
<button type="button" class="btn btn-danger delete-defender">제거</button>
</div>
</div>
</div>
<div class="card-body general_detail">
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">이름</span>
</div>
<input type="text" class="form-control form_general_name" value="무명" style="width:15ch;">
<div class="input-group-prepend">
<span class="input-group-text">직위</span>
</div>
<select class="custom-select form_general_level">
<select class="custom-select form_general_level" style="width:8ch;">
<option value="1">일반</option>
<option value="4">태수</option>
<option value="3">군사</option>
@@ -262,13 +257,7 @@ $startYear = $gameStor->getValue('startyear');
<span class="input-group-text">Level</span>
</div>
<input type="number" class="form-control form_exp_level" value="20" min="0" max="300" step="1">
<div class="input-group-prepend">
<span class="input-group-text">부상</span>
</div>
<input type="number" class="form-control form_injury" value="0" min="0" max="80" step="1">
<div class="input-group-append">
<span class="input-group-text">%(<span class="injury_helptext">건강</span>)</span>
</div>
</div>
<div class="input-group mb-1">
<div class="input-group-prepend">
@@ -311,10 +300,13 @@ $startYear = $gameStor->getValue('startyear');
</select>
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">자금</span>
<div class="input-group-prepend">
<span class="input-group-text">부상</span>
</div>
<input type="number" class="form-control form_injury" value="0" min="0" max="80" step="1">
<div class="input-group-append">
<span class="input-group-text">%(<span class="injury_helptext">건강</span>)</span>
</div>
<input type="number" class="form-control form_gold" value="0" min="0" max="40000" step="50">
<div class="input-group-prepend">
<span class="input-group-text">군량</span>
</div>
+321 -60
View File
@@ -5,24 +5,260 @@ jQuery(function($){
var $defenderHeaderForm = $('.form_sample .card-header');
var $defenderColumn = $('.defender-column');
var defenderNoList = {};
var $attackerCard = $('.attacker_form');
var initBasicEvent = function(){
$('.export_general').click(function(){
$('.form_injury').change(function(){
var $this = $(this);
var $card = $this.closest('.general_form');
var $general = $card.find('.general_detail');
var $general = getGeneralDetail($this);
var $helptext = $general.find('.injury_helptext');
var injury = parseInt($this.val());
//FIXME: PHP 코드와 항상 일치하도록 변경
var text = '건강';
var color = 'white';
if(injury > 60){
text = '위독';
color = 'red';
}
else if(injury > 40){
text = '심각';
color = 'magenta';
}
else if(injury > 20){
text = '중상';
color = 'orange';
}
else if(injury > 0){
text = '경상';
color = 'yellow';
}
$helptext.html(text).css('color', color);
});
$('.export_general').click(function(){
var $btn = $(this);
var $general = getGeneralDetail($btn);
var values = extractGeneralInfo($general);
var values = exportGeneralInfo($general);
console.log(values);
});
//$defenderHeaderForm.find('')
$('.delete-defender').click(function(){
var $card = getGeneralFrame($(this));
deleteDefender($card);
});
$('.copy-defender').click(function(){
var $card = getGeneralFrame($(this));
copyDefender($card);
});
$('.add-defender').click(function(){
addDefender();
});
$('.btn-general-load').click(function(){
var $file = $(this).prev();
$file[0].click();
})
$('.form_load_general_file').on('change', function(e){
e.preventDefault();
var $this = $(this);
var $card = getGeneralFrame($this);
var files = e.target.files;
importGeneralInfoByFile(files, $card);
return false;
});
$('.btn-general-save').click(function(){
var $this = $(this);
var $general = getGeneralDetail($this);
var generalData = exportGeneralInfo($general);
var filename = "general_{0}.json".format(generalData.name);
var saveData = JSON.stringify({
objType:'general',
data:generalData
}, null, 4);
download(saveData, filename, 'application/json');
});
var $generals = $('.general_detail');
$generals.bind('dragover dragleave', function(e) {
e.stopPropagation()
e.preventDefault()
})
$generals.bind('drop', function(e){
e.preventDefault();
var $this = $(this);
var $card = getGeneralFrame($this);
var files = e.originalEvent.dataTransfer.files;
importGeneralInfoByFile(files, $card);
return false;
});
}
var loadGeneralInfo = function($general, data){
var importGeneralInfo = function($general, data){
var setVal = function(query, val){
$general.find(query).val(val).change();
}
setVal('.form_general_name', data.name);
setVal('.form_general_level', data.level);
setVal('.form_exp_level', data.explevel);
setVal('.form_injury', data.injury);
setVal('.form_leadership', data.leader);
setVal('.form_general_horse', data.horse);
setVal('.form_power', data.power);
setVal('.form_general_weap', data.weap);
setVal('.form_intel', data.intel);
setVal('.form_general_book', data.book);
setVal('.form_general_item', data.item);
setVal('.form_injury', data.injury);
setVal('.form_rice', data.rice);
setVal('.form_general_character', data.personal);
setVal('.form_general_special_war', data.special2);
setVal('.form_crew', data.crew);
setVal('.form_crewtype', data.crewtype);
setVal('.form_atmos', data.atmos);
setVal('.form_train', data.train);
setVal('.form_dex0', data.dex0);
setVal('.form_dex10', data.dex10);
setVal('.form_dex20', data.dex20);
setVal('.form_dex30', data.dex30);
setVal('.form_dex40', data.dex40);
setVal('.form_defend_mode', data.mode);
if(!setGeneralNo($general, data.no)){
setGeneralNo($general, generateNewGeneralNo());
}
}
var extractGeneralInfoForDB = function($general, idx){
var retVal = extractGeneralInfo($general);
var exportGeneralInfo = function($general){
var getInt = function(query){
return parseInt($general.find(query).val());
}
var getVal = function(query){
return $general.find(query).val();
}
return {
no:getGeneralNo($general),
name:getVal('.form_general_name'),
level:getInt('.form_general_level'),
explevel:getInt('.form_exp_level'),
leader:getInt('.form_leadership'),
horse:getInt('.form_general_horse'),
power:getInt('.form_power'),
weap:getInt('.form_general_weap'),
intel:getInt('.form_intel'),
book:getInt('.form_general_book'),
item:getInt('.form_general_item'),
injury:getInt('.form_injury'),
rice:getInt('.form_rice'),
personal:getInt('.form_general_character'),
special2:getInt('.form_general_special_war'),
crew:getInt('.form_crew'),
crewtype:getInt('.form_crewtype'),
atmos:getInt('.form_atmos'),
train:getInt('.form_train'),
dex0:getInt('.form_dex0'),
dex10:getInt('.form_dex10'),
dex20:getInt('.form_dex20'),
dex30:getInt('.form_dex30'),
dex40:getInt('.form_dex40'),
mode:getInt('.form_defend_mode'),
};
}
var importGeneralInfoByFile = function(files, $card){
if($card === undefined){
$card = addDefender();
}
if(files === null){
alert('파일 에러!');
return false;
}
if(files.length < 1){
alert("파일 에러!");
return false;
}
var file = files[0];
if(file.size > 1024*1024){
alert('파일이 너무 큽니다!');
return false;
}
if(file.type === ''){
alert('폴더를 업로드할 수 없습니다!');
return false;
}
var reader = new FileReader();
reader.onload = function(){
var generalData = {};
try {
generalData = JSON.parse(reader.result);
} catch(e) {
alert('올바르지 않은 파일 형식입니다');
return false;
}
if(!('objType' in generalData)){
alert('파일 형식을 확인할 수 없습니다');
return false;
}
if(generalData.objType != 'general'){
alert('장수 데이터가 아닙니다');
return false;
}
$card.find('.form_load_general_file').val('');
importGeneralInfo($card, generalData.data);
return true;
};
try {
reader.readAsText(file);
}
catch(e) {
alert('파일을 읽는데 실패했습니다.');
return false;
}
return true;
}
var exportGeneralInfoForDB = function($general, idx){
var retVal = exportGeneralInfo($general);
var dbVal = {
turntime:'2018-08-26 12:00',
@@ -30,6 +266,8 @@ jQuery(function($){
power2:0,
intel2:0,
gold:10000,
dedication:0,
warnum:10,
killnum:4,
@@ -38,78 +276,101 @@ jQuery(function($){
killcrew:20000,
deathcrew:20000,
recwar:'SUCCESS',
experience:extInt('.form_exp_level')*extInt('.form_exp_level'),
experience:Math.pow(retVal.explevel, 2),
};
if(idx <= 0){
dbVal['name'] = '출병자';
dbVal['no'] = 1;
dbVal['nation'] = 1;
}
else{
dbVal['name'] = '수비자{0}'.format(idx);
dbVal['no'] = idx+1;
dbVal['nation'] = 2;
}
return $.merge(retVal, defaultVal);
}
var extractGeneralInfo = function($general){
var extInt = function(query){
return parseInt($general.find(query).val());
var getGeneralFrame = function($btn){
var $card = $btn.closest('.general_form');
return $card;
}
var getGeneralDetail = function($btn){
var $card = getGeneralFrame($btn);
var $general = $card.find('.general_detail');
return $general;
}
var getGeneralNo = function($btn){
return parseInt(getGeneralFrame($btn).data('general_no'));
}
var setGeneralNo = function($btn, value){
if(value == 1){
//1번은 무조건 공격자임
return false;
}
return {
level:extInt('.form_general_level'),
explevel:extInt('.form_exp_level'),
injury:extInt('.form_injury'),
leader:extInt('.form_leadership'),
horse:extInt('.form_general_horse'),
power:extInt('.form_power'),
weap:extInt('.form_general_weap'),
intel:extInt('.form_intel'),
book:extInt('.form_general_book'),
item:extInt('.form_general_item'),
gold:extInt('.form_gold'),
rice:extInt('.form_rice'),
personal:extInt('.form_general_character'),
special2:extInt('.form_general_special_war'),
crew:extInt('.form_crew'),
crewtype:extInt('.form_crewtype'),
atmos:extInt('.form_atmos'),
train:extInt('.form_train'),
dex0:extInt('.form_dex0'),
dex10:extInt('.form_dex10'),
dex20:extInt('.form_dex20'),
dex30:extInt('.form_dex30'),
dex40:extInt('.form_dex40'),
mode:extInt('.form_defend_mode'),
};
if(value in defenderNoList){
return false;
}
var $card = getGeneralFrame($btn);
$card.data('general_no', value);
defenderNoList[value] = $card;
return true;
}
initBasicEvent();
$('.defender_form').append($defenderHeaderForm.clone(true, true));
$('.general_form').append($generalForm.clone(true, true));
var addDefender = function(){
var $newObj = $('<div class="card mb-2 defender_form general_form"></div>');
$defenderColumn.append($newObj);
$newObj.append($defenderHeaderForm.clone(true,true));
$newObj.append($generalForm.clone(true,true));
var generateNewGeneralNo = function(){
while(true){
var newGeneralNo = parseInt(Math.random()*(1<<24))+2;
if(newGeneralNo in defenderNoList){
continue;
}
return newGeneralNo;
}
}
var deleteDefender = function($this){
var $card = $this.closest('.general_form');
var deleteGeneralNo = function($btn){
var $card = getGeneralFrame($btn);
$card.removeData('general_no');
var generalNo = getGeneralNo($card);
delete defenderNoList[generalNo];
}
var addDefender = function($cardAfter){
var $newCard = $('<div class="card mb-2 defender_form general_form"></div>');
if($cardAfter === undefined){
$defenderColumn.append($newCard);
}
else{
$cardAfter.after($newCard);
}
$newCard.append($defenderHeaderForm.clone(true,true));
$newCard.append($generalForm.clone(true,true));
$newGeneral = getGeneralDetail($newCard);
setGeneralNo($newCard, generateNewGeneralNo());
return $newCard;
}
var deleteDefender = function($card){
deleteGeneralNo($card);
$card.detach();
}
$('.add-defender').click(addDefender);
$('.delete-defender').click(function(){deleteDefender($(this));});
var copyDefender = function($card){
var $general = getGeneralDetail($card);
var generalData = exportGeneralInfo($general);
var $newObj = addDefender($card);
importGeneralInfo(getGeneralDetail($newObj), generalData);
}
initBasicEvent();
$attackerCard.append($generalForm.clone(true,true));
addDefender();
});