foundryvtt-reve-de-dragon/module/tirage/fenetre-recherche-tirage.js

217 lines
11 KiB
JavaScript

import { RdDItem } from '../item.js';
import { HtmlUtility } from '../html-utility.js';
import { Misc } from "../misc.js";
import { CompendiumTable, CompendiumTableHelpers, SystemCompendiums } from '../settings/system-compendiums.js';
import { RdDRaretes } from './raretes.js';
const FILTER_GROUPS = [
{ group: 'type', label: "Type d'objet" },
{ group: 'comestible', label: 'Alimentaire' },
{ group: 'categorie', label: 'Utilisation' },
{ group: 'milieu', label: 'Milieu' },
{ group: 'rarete', label: 'Rarete' },
{ group: 'qualite', label: 'Qualité' },
{ group: 'enc', label: 'Encombrement' },
{ group: 'prix', label: 'Prix' },
]
const FILTERS = [
{ group: 'comestible', code: 'pret', label: 'Comestible', check: item => item.isComestible() == 'pret' },
{ group: 'comestible', code: 'alcool', label: 'Alcool', check: item => item.isAlcool() },
{ group: 'comestible', code: 'boisson', label: 'Boisson', check: item => item.isNourritureBoisson() && item.system.boisson },
{ group: 'comestible', code: 'brut', label: 'A préparer', check: item => item.isComestible() == 'brut' },
{ group: 'comestible', code: 'poison', label: 'Toxique', check: item => item.isComestible() == 'poison' },
{ group: 'comestible', code: 'non', label: 'Immangeable', check: item => !item.isComestible() || item.isComestible() == '' },
{ group: 'categorie', code: 'alchimie', label: 'Alchimique', check: item => item.isEnvironnement() && item.system.categorie == 'Alchimie' },
{ group: 'categorie', code: 'cuisine', label: 'Cuisine', check: item => item.isEnvironnement() && item.system.categorie == 'Cuisine' },
{ group: 'categorie', code: 'repos', label: 'Repos', check: item => item.isEnvironnement() && item.system.categorie == 'Repos' },
{ group: 'categorie', code: 'soins', label: 'Soins', check: item => item.isEnvironnement() && item.system.categorie == 'Soin' },
{ group: 'categorie', code: 'autres', label: 'Autres', check: item => !item.isEnvironnement() || ['', 'Autre'].includes(item.system.categorie) },
{ group: "qualite", code: "mauvaise", label: "Mauvaise (négative)", check: item => item.isInventaire() && item.system.qualite < 0 },
{ group: "qualite", code: "quelconque", label: "Quelconque (0)", check: item => item.isInventaire() && item.system.qualite == 0 },
{ group: "qualite", code: "correcte", label: "Correcte (1-3)", check: item => item.isInventaire() && 1 <= item.system.qualite && item.system.qualite <= 3 },
{ group: "qualite", code: "bonne", label: "Bonne (4-6)", check: item => item.isInventaire() && 4 <= item.system.qualite && item.system.qualite <= 6 },
{ group: "qualite", code: "excellente", label: "Excellente (7-9)", check: item => item.isInventaire() && 7 <= item.system.qualite && item.system.qualite <= 9 },
{ group: "qualite", code: "mythique", label: "Mythique (10+)", check: item => item.isInventaire() && 10 <= item.system.qualite },
{ group: "enc", code: "negligeable", label: "Négligeable (jusqu'à 0.1)", check: item => item.isInventaire() && item.system.encombrement <= 0.1 },
{ group: "enc", code: "leger", label: "Léger (0.1 à 0.5)", check: item => item.isInventaire() && 0.1 < item.system.encombrement && item.system.encombrement <= 0.5 },
{ group: "enc", code: "moyen", label: "Moyen (0.5 à 1.5)", check: item => item.isInventaire() && 0.5 < item.system.encombrement && item.system.encombrement <= 1.5 },
{ group: "enc", code: "lourd", label: "Lourd (1.5 à 3)", check: item => item.isInventaire() && 1.5 < item.system.encombrement && item.system.encombrement <= 3 },
{ group: "enc", code: "massif", label: "Massif (3 à 10)", check: item => item.isInventaire() && 3 < item.system.encombrement && item.system.encombrement <= 10 },
{ group: "enc", code: "anemort", label: "Un âne mort (plus de 10)", check: item => item.isInventaire() && 10 < item.system.encombrement },
{ group: "prix", code: "gratuit", label: "Gratuit", check: item => item.isInventaire() && item.system.cout == 0 },
{ group: "prix", code: "deniers", label: "Deniers (étain) 1-9", check: item => item.isInventaire() && 0 < item.system.cout && item.system.cout < 0.1 },
{ group: "prix", code: "bronze", label: "Bronzes 1-9", check: item => item.isInventaire() && 0.1 <= item.system.cout && item.system.cout < 1 },
{ group: "prix", code: "sols", label: "Sols (argent) 1-9", check: item => item.isInventaire() && 1 <= item.system.cout && item.system.cout < 10 },
{ group: "prix", code: "dragons", label: "Dragons (or) 1+ ", check: item => item.isInventaire() && 10 <= item.system.cout },
]
export class FenetreRechercheTirage extends Application {
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
template: "systems/foundryvtt-reve-de-dragon/templates/tirage/fenetre-recherche-tirage.hbs",
title: `Recherches et tirages`,
width: 600,
height: 600,
popOut: true,
resizable: true
});
}
static async $filterMilieux() {
const milieux = await game.system.rdd.environnement.milieux();
return milieux.map(m => { return { group: 'milieu', code: m, label: m, check: item => item.isPresentDansMilieux(m) } })
}
static $filterRarete() {
return RdDRaretes.raretes()
.map(r => { return { group: 'rarete', code: r.code, label: r.label, check: item => item.getRarete()?.code == r.code }; });
}
static $filterTypes() {
return [
{ group: 'type', code: 'inventaire', label: 'Inventaire', check: item => item.isInventaire() && !item.isEnvironnement() },
]
.concat(['arme', 'armure'].map(it => FenetreRechercheTirage.$typeToFilter(it)))
.concat([{ group: 'type', code: 'environement', label: 'Faune, Flore, Ingrédients', check: item => item.isEnvironnement() }])
.concat(RdDItem.getItemTypesEnvironnement().map(it => FenetreRechercheTirage.$typeToFilter(it)))
}
static $typeToFilter(type) { return { group: 'type', code: type, label: Misc.typeName('Item', type), check: item => item.type == type }; }
static async create(tirage = {}) {
new FenetreRechercheTirage(tirage).render(true);
}
constructor(tirage) {
super();
this.tirage = tirage;
this.compendiums = [
SystemCompendiums.getCompendium('faune-flore-mineraux'),
SystemCompendiums.getCompendium('equipement')
]
}
async getData() {
const filterGroups = duplicate(FILTER_GROUPS);
FILTERS
.concat(FenetreRechercheTirage.$filterTypes())
.concat(await FenetreRechercheTirage.$filterMilieux())
.concat(FenetreRechercheTirage.$filterRarete())
.forEach(f => addFilterToGroup(filterGroups, f))
mergeObject(this.tirage,
{
filterGroups: filterGroups.filter(it => it.group)
})
let formData = super.getData();
mergeObject(formData, this.tirage)
return formData;
function addFilterToGroup(filterGroups, filter) {
if (filter.group && filter.code && filter.label) {
let fg = filterGroups.find(g => g.group == filter.group);
if (fg == undefined) {
filterGroups.push({ group: filter.group, label: filter.group, filters: [filter] })
}
else if (fg.filters == undefined) {
fg.filters = [filter];
}
else {
fg.filters.push(filter);
}
}
else {
console.warn("Filtre incorrect, pas de groupe/code/label", filter);
}
}
}
activateListeners(html) {
super.activateListeners(html);
this.html = html;
HtmlUtility.showControlWhen(this.html.find('div.group-filters'), false);
HtmlUtility.showControlWhen(this.html.find('i.filter-group-hide'), false);
HtmlUtility.showControlWhen(this.html.find('i.filter-group-show'), true);
this.html.find("a.filter-group-toggle").click(event => {
const groupDiv = this.html.find(event.currentTarget)?.parents('div.filter-group').first();
const visible = groupDiv.find('div.group-filters').first().is(":visible");
this.showFilterGroup(groupDiv, !visible)
});
this.html.find("input.activate-filter").change(event => this.changeListeFiltresActifs())
this.html.find("a.supprimer-filtres").click(async event => this.html.find('input.activate-filter:checked').prop("checked", false))
this.html.find("a.recherche-filtres").click(async event => {
const table = await this.buildTable();
this.html.find('div.liste-resultats').html(await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/tirage/liste-resultats.hbs`, { resultats: table }));
})
this.html.find("a.tirage-filtres").click(async event => {
const table = await this.buildTable();
const row = await CompendiumTableHelpers.getRandom(table, 'Item')
await CompendiumTableHelpers.tableRowToChatMessage(row, 'Item');
})
}
async buildTable() {
const filter = this.getSelectedItemsFilter();
const equipementCompendiumTable = new CompendiumTable('equipement', 'Item');
const equipements = await equipementCompendiumTable.buildTable(it => it.getFrequence(), filter)
const environnements = await game.system.rdd.environnement.buildEnvironnementTable(undefined, filter);
return CompendiumTableHelpers.concatTables(environnements, equipements);
}
getSelectedItemsFilter() {
const byGroup = this.getSelectedFiltersByGroup();
const groupSummaries = Object.entries(byGroup).map(([key, list]) => {
const group = this.tirage.filterGroups.find(g => key == g.group);
const filters = list.map(it => it.code).map(code => group.filters.find(f => code == f.code))
return filters
.map(f => f.check)
.reduce((a, b) => { return it => a(it) || b(it) });;
});
if (groupSummaries.length == 0) {
return it => true;
}
return groupSummaries.reduce((a, b) => { return it => a(it) && b(it) })
}
showFilterGroup(groupDiv, show) {
if (groupDiv) {
HtmlUtility.showControlWhen(groupDiv.find('div.group-filters'), show);
HtmlUtility.showControlWhen(groupDiv.find('i.filter-group-hide'), show);
HtmlUtility.showControlWhen(groupDiv.find('i.filter-group-show'), !show);
}
}
changeListeFiltresActifs() {
const byGroup = this.getSelectedFiltersByGroup();
const groupSummaries = Object.entries(byGroup).map(([key, list]) => {
const group = this.tirage.filterGroups.find(g => key == g.group);
const filters = list.map(it => it.code).map(code => group.filters.find(f => code == f.code))
return group.label + ': ' + filters
.map(f => f.label)
.reduce(Misc.joining(', '));;
});
const fullText = groupSummaries.length == 0 ? "" : groupSummaries.reduce(Misc.joining(' - '));
this.html.find('span.liste-filtres-actifs').text(fullText);
}
getSelectedFiltersByGroup() {
const selectedFilters = jQuery.map(this.html.find('input.activate-filter:checked'), it => {
const element = this.html.find(it);
return { group: element.data('group'), code: element.data('code') };
});
const byGroup = Misc.classify(selectedFilters, it => it.group);
return byGroup;
}
}