Initialisation du repo

This commit is contained in:
RyujiDanma 2022-05-31 21:39:31 +02:00
commit c90fa0d4db
2 changed files with 599 additions and 0 deletions

229
app.js Normal file
View File

@ -0,0 +1,229 @@
(function () {
angular.module('app', ['angular-locker']);
AppCtrl.$inject = ['$http', 'locker'];
function AppCtrl($http, locker) {
var vm = this;
vm.simultaneous = locker.get('simultaneous');
vm.totalSteps = 34;
vm.sorting = locker.get('sorting', 0);
vm.saveData = locker.get('save');
vm.displayOwnedMonsters = locker.get('displayOwnedMonsters', true);
vm.displayFinishedZones = locker.get('displayFinishedZones', true);
vm.displayFinishedSteps = locker.get('displayFinishedSteps', true);
vm.isOwned = function(monster) {
if (!vm.saveData || !monster) {
return false;
}
return vm.saveData.find(el => el[0] === monster.id) && vm.saveData.find(el => el[0] === monster.id)[1] >= vm.simultaneous;
};
vm.saveMonster = function(monster, val) {
vm.saveData = locker.get('save', []);
if (vm.saveData.find(savedMonster => savedMonster[0] === monster.id)) {
vm.saveData[vm.saveData.findIndex(savedMonster => savedMonster[0] === monster.id)][1] = monster.owned;
} else {
vm.saveData.push([monster.id, monster.owned]);
}
locker.put('save', vm.saveData);
};
vm.increase = function(monster) {
monster.owned++;
vm.saveMonster(monster);
};
vm.decrease = function(monster) {
if(monster.owned > 0) {
monster.owned--;
}
vm.saveMonster(monster);
};
vm.saveSimultaneous = function () {
locker.put('simultaneous', vm.simultaneous)
}
vm.owned = function(type, zone, step) {
if (!vm.monsters) {
return '?';
}
return vm.monsters.filter(function(monster) {
if (!vm.isOwned(monster)) {
return false;
}
if (!type && !zone && !step) {
return true;
}
if (type && monster.type == type) {
return true;
}
if (zone && monster.zones.indexOf(zone) >= 0) {
return true;
}
if (step && monster.step == step) {
return true;
}
return false;
}).length;
};
vm.ownedPercentage = function(type, zone, step) {
return Math.ceil(vm.owned(type, zone, step) * 100 / vm.total(type, zone, step)) || 0;
};
vm.total = function(type, zone, step) {
if (!vm.monsters) {
return '?';
}
return vm.monsters.filter(function(monster) {
if (type) {
return monster.type == type;
}
if (zone) {
return monster.zones.indexOf(zone) >= 0;
}
if (step) {
return monster.step == step;
}
return true;
}).length;
};
vm.load = function() {
locker.put('save', vm.loadData.match(/\d+,\d+/gm).map(function(id) {
return [+id.split(',')[0],+id.split(',')[1]];
}));
vm.saveData = locker.get('save');
};
vm.toggleZone = function(zone) {
var newVal = true;
if (vm.owned(false, zone) == vm.total(false, zone)) {
newVal = false;
}
vm.monsters.map(function(monster) {
if (monster.zones.indexOf(zone) >= 0) {
vm.toggleMonster(monster, newVal);
}
});
};
vm.toggleStep = function(step) {
var newVal = vm.simultaneous;
if (vm.owned(false, false, step) == vm.total(false, false, step)) {
newVal = 0;
}
vm.monsters.map(function(monster) {
if (monster.step == step) {
monster.owned = newVal;
vm.saveMonster(monster);
}
});
};
vm.completedSteps = function() {
if (!vm.monsters) {
return '??';
}
return vm.monsters.map(function(monster) {
return monster.step;
}).sort().filter(function(step, index, steps) {
return index == steps.indexOf(step);
}).filter(function(step) {
return vm.ownedPercentage(false, false, step) == 100;
}).length;
};
vm.completedStepsPercentage = function() {
return Math.ceil(vm.completedSteps() * 100 / vm.totalSteps);
};
vm.chooseSorting = function(sorting) {
vm.sorting = sorting;
locker.put('sorting', sorting);
};
vm.toggleOwnedMonsters = function() {
locker.put('displayOwnedMonsters', vm.displayOwnedMonsters);
}
vm.toggleFinishedZones = function() {
locker.put('displayFinishedZones', vm.displayFinishedZones);
}
vm.toggleFinishedSteps = function() {
locker.put('displayFinishedSteps', vm.displayFinishedSteps);
}
vm.resetAll = function() {
if (confirm('Dernière chance !')) {
locker.clean();
vm.sorting = 0;
vm.saveData = null;
vm.displayOwnedMonsters = true;
vm.displayFinishedZones = true;
vm.displayFinishedSteps = true;
vm.zones = {};
vm.steps = [];
vm.monsters = [];
$('#saveModal').modal('hide');
}
};
$http.get('https://raw.githubusercontent.com/Mopolo/Eternelle-Moisson/gh-pages/monsters.json').then(function(res) {
vm.monsters = res.data;
vm.monsters.forEach(monster => {
monster.owned = vm.saveData?.find(el => el[0] === monster.id) ? vm.saveData.find(el => el[0] === monster.id)[1] : 0
})
vm.zones = {};
vm.steps = [];
angular.forEach(vm.monsters, function(monster) {
angular.forEach(monster.zones, function(zone) {
if (angular.isUndefined(vm.zones[zone])) {
vm.zones[zone] = [];
}
vm.zones[zone].push(monster);
});
if (angular.isUndefined(vm.steps[monster.step])) {
vm.steps[monster.step] = [];
}
vm.steps[monster.step].push(monster);
});
});
}
angular.module('app')
.controller('AppCtrl', AppCtrl);
}());

370
index.html Normal file
View File

@ -0,0 +1,370 @@
<!DOCTYPE html>
<html lang="fr" ng-app="app">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>L'Éternelle moisson - Dofus Ocre</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootswatch/3.3.6/united/bootstrap.min.css" />
<style>
body {
padding-top: 60px;
}
.label {
margin-right: 5px;
}
tbody tr {
cursor: pointer;
}
</style>
</head>
<body ng-controller="AppCtrl as appCtrl">
<a href="https://github.com/Mopolo/Eternelle-Moisson"><img style="position: absolute; top: 0; right: 0; border: 0;z-index: 10000;" src="https://camo.githubusercontent.com/38ef81f8aca64bb9a64448d0d70f1308ef5341ab/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f6461726b626c75655f3132313632312e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png"></a>
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">L'Éternelle moisson ({{ appCtrl.owned() }}/{{ appCtrl.monsters.length }})</a>
</div>
<div id="navbar" class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li ng-class="{active: appCtrl.sorting == 0}"><a href="#" ng-click="appCtrl.chooseSorting(0)">Ordre alphabétique</a></li>
<li ng-class="{active: appCtrl.sorting == 1}"><a href="#" ng-click="appCtrl.chooseSorting(1)">Zones</a></li>
<li ng-class="{active: appCtrl.sorting == 2}"><a href="#" ng-click="appCtrl.chooseSorting(2)">Étapes</a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li><a href="#" data-toggle="modal" data-target="#saveModal">Sauvegarde</a></li>
<li><a href="#" data-toggle="modal" data-target="#helpModal">Aide</a></li>
<li><a href="#" data-toggle="modal" data-target="#aboutModal">A propos</a></li>
</ul>
</div><!--/.nav-collapse -->
</div>
</nav>
<div class="container">
<div class="row">
<div class="col-xs-12">
<div class="row">
<div class="col-xs-12">
<div class="row">
<div class="col-xs-12 col-sm-3">
Monstres : {{ appCtrl.owned('monster') }}/{{ appCtrl.total('monster') }}
<div class="progress">
<div class="progress-bar progress-bar-primary progress-bar-striped" role="progressbar" aria-valuenow="{{ appCtrl.ownedPercentage('monster') }}" aria-valuemin="0" aria-valuemax="100" style="min-width: 2em; width: {{ appCtrl.ownedPercentage('monster') }}%;">
{{ appCtrl.ownedPercentage('monster') }}%
</div>
</div>
</div>
<div class="col-xs-12 col-sm-3">
Boss : {{ appCtrl.owned('boss') }}/{{ appCtrl.total('boss') }}
<div class="progress">
<div class="progress-bar progress-bar-primary progress-bar-striped" role="progressbar" aria-valuenow="{{ appCtrl.ownedPercentage('boss') }}" aria-valuemin="0" aria-valuemax="100" style="min-width: 2em; width: {{ appCtrl.ownedPercentage('boss') }}%;">
{{ appCtrl.ownedPercentage('boss') }}%
</div>
</div>
</div>
<div class="col-xs-12 col-sm-3">
Archimonstres : {{ appCtrl.owned('archi') }}/{{ appCtrl.total('archi') }}
<div class="progress">
<div class="progress-bar progress-bar-primary progress-bar-striped" role="progressbar" aria-valuenow="{{ appCtrl.ownedPercentage('archi') }}" aria-valuemin="0" aria-valuemax="100" style="min-width: 2em; width: {{ appCtrl.ownedPercentage('archi') }}%;">
{{ appCtrl.ownedPercentage('archi') }}%
</div>
</div>
</div>
<div class="col-xs-12 col-sm-3">
Etapes : {{ appCtrl.completedSteps() }}/{{ appCtrl.totalSteps }}
<div class="progress">
<div class="progress-bar progress-bar-primary progress-bar-striped" role="progressbar" aria-valuenow="{{ appCtrl.ownedPercentage('archi') }}" aria-valuemin="0" aria-valuemax="100" style="min-width: 2em; width: {{ appCtrl.ownedPercentage('archi') }}%;">
{{ appCtrl.ownedPercentage('archi') }}%
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12">
Total : {{ appCtrl.owned() }}/{{ appCtrl.monsters.length }}
<div class="progress">
<div class="progress-bar progress-bar-primary progress-bar-striped" role="progressbar" aria-valuenow="{{ appCtrl.ownedPercentage() }}" aria-valuemin="0" aria-valuemax="100" style="min-width: 2em; width: {{ appCtrl.ownedPercentage() }}%;">
{{ appCtrl.ownedPercentage() }}%
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-3">
Nombre de chasses simultanées :
<input class="form-control" type="number" ng-model="appCtrl.simultaneous" ng-change="appCtrl.saveSimultaneous()">
</div>
</div>
<div ng-if="appCtrl.sorting == 0">
<div>
<div class="checkbox">
<label>
<input type="checkbox" ng-model="appCtrl.displayOwnedMonsters" ng-change="appCtrl.toggleOwnedMonsters()" /> Masquer les monstres possédés
</label>
</div>
</div>
<table class="table table-stripped table-hover table-bordered">
<thead>
<tr>
<th style="width:100px;">Possédé</th>
<th>Nom</th>
<th>Étape</th>
<th>Zones</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="monster in appCtrl.monsters | orderBy:'name'" ng-class="{success: appCtrl.isOwned(monster)}" ng-hide="appCtrl.displayOwnedMonsters && appCtrl.isOwned(monster)">
<td><button class="btn btn-info btn-xs" ng-click="appCtrl.increase(monster)"><i class="glyphicon glyphicon-plus"></i></button> {{ monster.owned ? monster.owned : 0 }} <button class="btn btn-info btn-xs" ng-click="appCtrl.decrease(monster)"><i class="glyphicon glyphicon-minus"></i></button></td>
<td>
<i class="glyphicon glyphicon-star" ng-if="monster.type == 'boss'"></i>
<i class="glyphicon glyphicon-fire" ng-if="monster.type == 'archi'"></i>
{{ monster.name }}
</td>
<td>{{ monster.step }}</td>
<td>
<span class="label label-primary" ng-repeat="zone in monster.zones">{{ zone }}</span>
</td>
</tr>
</tbody>
</table>
</div>
<div ng-if="appCtrl.sorting == 1">
<div class="checkbox">
<label>
<input type="checkbox" ng-model="appCtrl.displayFinishedZones" ng-change="appCtrl.toggleFinishedZones()" /> Masquer les zones terminées
</label>
</div>
<div class="panel panel-default" ng-repeat="(zone, monsters) in appCtrl.zones" ng-hide="appCtrl.displayFinishedZones && appCtrl.owned(false, zone) == appCtrl.total(false, zone)">
<div class="panel-heading">
{{ zone }} ({{ appCtrl.owned(false, zone) }}/{{ appCtrl.total(false, zone) }})
<div class="pull-right">
<button class="btn btn-info btn-xs" ng-click="appCtrl.toggleZone(zone)">
Tout <span ng-if="appCtrl.owned(false, zone) == appCtrl.total(false, zone)"></span>cocher
</button>
</div>
</div>
<table class="table table-bordered">
<thead>
<tr>
<th style="width:100px;">Possédé</th>
<th>Nom</th>
<th>Étape</th>
<th>Zones</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="monster in monsters" ng-class="{success: appCtrl.isOwned(monster)}">
<td><button class="btn btn-info btn-xs" ng-click="appCtrl.increase(monster)"><i class="glyphicon glyphicon-plus"></i></button> {{ monster.owned ? monster.owned : 0 }} <button class="btn btn-info btn-xs" ng-click="appCtrl.decrease(monster)"><i class="glyphicon glyphicon-minus"></i></button></td>
<td>
<i class="glyphicon glyphicon-star" ng-if="monster.type == 'boss'"></i>
<i class="glyphicon glyphicon-fire" ng-if="monster.type == 'archi'"></i>
{{ monster.name }}
</td>
<td>{{ monster.step }}</td>
<td>
<span class="label label-primary" ng-repeat="zone in monster.zones">{{ zone }}</span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div ng-if="appCtrl.sorting == 2">
<div class="checkbox">
<label>
<input type="checkbox" ng-model="appCtrl.displayFinishedSteps" ng-change="appCtrl.toggleFinishedSteps()" /> Masquer les étapes terminées
</label>
</div>
<div class="panel panel-default" ng-repeat="(step, monsters) in appCtrl.steps" ng-hide="step == 0 || (appCtrl.displayFinishedSteps && appCtrl.owned(false, false, step) == appCtrl.total(false, false, step))">
<div class="panel-heading">
Étape {{ step }} ({{ appCtrl.owned(false, false, step) }}/{{ appCtrl.total(false, false, step) }})
<div class="pull-right">
<button class="btn btn-info btn-xs" ng-click="appCtrl.toggleStep(step)">
Tout <span ng-if="appCtrl.owned(false, false, step) == appCtrl.total(false, false, step)"></span>cocher
</button>
</div>
</div>
<table class="table table-bordered">
<thead>
<tr>
<th style="width:100px;">Possédé</th>
<th>Nom</th>
<th>Zones</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="monster in monsters" ng-class="{success: appCtrl.isOwned(monster)}">
<td><button class="btn btn-info btn-xs" ng-click="appCtrl.increase(monster)"><i class="glyphicon glyphicon-plus"></i></button> {{ monster.owned ? monster.owned : 0 }} <button class="btn btn-info btn-xs" ng-click="appCtrl.decrease(monster)"><i class="glyphicon glyphicon-minus"></i></button></td>
<td>
<i class="glyphicon glyphicon-star" ng-if="monster.type == 'boss'"></i>
<i class="glyphicon glyphicon-fire" ng-if="monster.type == 'archi'"></i>
{{ monster.name }}
</td>
<td>
<span class="label label-primary" ng-repeat="zone in monster.zones">{{ zone }}</span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<p>
Cet outil facilite la gestion de la quête du Dofus Ocre.
<a href="https://github.com/Mopolo/Eternelle-Moisson">Voir sur Github</a>
<span class="pull-right">Dofus est la propriété d'Ankama</span>
</p>
</div>
</div>
</div>
<div class="modal fade" id="saveModal" tabindex="-1" role="dialog" aria-labelledby="saveModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="saveModalLabel">Gestion de la sauvegarde</h4>
</div>
<div class="modal-body">
<div class="form-group">
<label for="inputSave">Sauvegarde actuelle</label>
<input type="text" name="save" id="inputSave" class="form-control" ng-model="appCtrl.saveData" />
</div>
<hr />
<div class="form-group">
<label for="inputLoad">Charger une sauvegarde</label>
<div class="input-group">
<input type="text" name="load" id="inputLoad" class="form-control" ng-model="appCtrl.loadData" />
<span class="input-group-btn">
<button class="btn btn-warning" type="button" ng-click="appCtrl.load()" ng-disabled="!appCtrl.loadData.length">Charger</button>
</span>
</div>
</div>
<hr />
<div class="text-center">
<h4>ATTENTION CELA VA TOUT EFFACER !!</h4>
<button class="btn btn-danger" ng-click="appCtrl.resetAll()">Remise à zéro</button>
</div>
<p class="text-danger" ng-show="appCtrl.loadData.length">Attention ! Charger une sauvegarde effacera les données actuelles.</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal">Fermer</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="helpModal" tabindex="-1" role="dialog" aria-labelledby="helpModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="helpModalLabel">Aide</h4>
</div>
<div class="modal-body">
<p>
Cet outils permet de faciliter la gestion de la quête du Dofus Ocre.
</p>
<p>
Pour ajouter ou supprimer un monstre il suffit de cliquer sur sa ligne.<br />
La sauvegarde se fait automatiquement et il n'y a pas besoin de compte.<br />
Les données sont enregistrées localement dans le navigateur. Vous pouvez donc fermer la page
et revenir plus tard.
</p>
<p>
Si vous changez de navigateur vous pouvez exporter la sauvegarde pour la charger plus tard.
</p>
<p>
Si vous trouvez un bug, avez une idée ou si la liste des monstres n'est pas à jour,
contribuez sur <a href="https://github.com/Mopolo/Eternelle-Moisson">Github</a> en faisant
une Pull Request ou en créant une issue.
</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal">Fermer</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="aboutModal" tabindex="-1" role="dialog" aria-labelledby="aboutModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="aboutModalLabel">A Propos</h4>
</div>
<div class="modal-body">
<p>
Ce site est libre et open source sur <a href="https://github.com/Mopolo/Eternelle-Moisson">Github</a>
et est écrit en AngularJS (version 1.x).
</p>
<p>
Les contributions sont les bienvenues.
</p>
<p>
Le code source est distribué sous licence MIT, vous avez donc le droit de le copier/modifier/distribuer
et de l'héberger vous même si vous préférez.
</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal">Fermer</button>
</div>
</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.min.js"></script>
<script src="https://cdn.jsdelivr.net/angular.locker/2.0.4/angular-locker.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" crossorigin="anonymous"></script>
<script src="app.js" type="text/javascript"></script>
</body>
</html>