"use strict";Object.defineProperty(exports,"__esModule",{value:!0});const egg_1=require("egg"),moment=require("moment");class EvaluationService extends egg_1.Service{async selectRange(g,a=g,b){const{mysql:c}=this.app,d=b&&b.trim()?` evaluation.station = '${b}' AND`:"",e=await c.query(`SELECT evaluation.station AS stationId, excellent, good, ordinary, bad, abandoned, date, station.name AS stationName FROM evaluation, station WHERE${d} date >= ? AND date <= ? AND evaluation.station = station.id`,[g,a]);return e}async selectSpecific(e,a){const{app:b}=this,c=await b.mysql.query("SELECT evaluation.station AS stationId, excellent, good, ordinary, bad, abandoned, date, station.name AS stationName FROM evaluation, station WHERE date = ? AND evaluation.station = ? AND evaluation.station = station.id",[a,e]);return c}calculateScore(l,a,b){const{excellent:c,good:d,ordinary:e,bad:f,abandoned:g}=l,h=c+d+e+f+g,i=h/b,j=1>i?1:i;return Math.round(100*((5*c+3*d+1*e+-4*f+0*g)/h*a*j))}async bestStationInRange(i,a=i){const b=await this.selectRange(i,a);if(0===b.length)return null;const{sum:c,statisticList:d}=this.summarizeEvaluation(b),e=c/d.length,f=moment.duration(moment(a).diff(moment(i))).days()+1,g=d.reduce((c,a)=>(void 0===c.score&&(c.score=this.calculateScore(c,f,e)),void 0===a.score&&(a.score=this.calculateScore(a,f,e)),a.score>c.score?a:c));return g}async summarizeRangeWithoutStation(f,a=f){const b=await this.selectRange(f,a),c=this.summarizeEvaluation(b),d=c.statisticList.reduce((c,a)=>(c.excellent+=a.excellent,c.good+=a.good,c.ordinary+=a.ordinary,c.bad+=a.bad,c.abandoned+=a.abandoned,c),{excellent:0,good:0,ordinary:0,bad:0,abandoned:0});return Object.assign({},d,{sum:c.sum})}summarizeEvaluation(d){const e={};let b=0;return d.forEach(c=>{e[c.stationId]?(e[c.stationId].excellent+=c.excellent,e[c.stationId].good+=c.good,e[c.stationId].ordinary+=c.ordinary,e[c.stationId].bad+=c.bad,e[c.stationId].abandoned+=c.abandoned):e[c.stationId]=c,b+=c.excellent+c.good+c.ordinary+c.bad+c.abandoned}),{sum:b,statisticList:Object.values(e)}}async rankInRange(k,a=k){const b=moment(a).diff(moment(k),"day")+1,c=await this.selectRange(k,a),{statisticList:d,sum:e}=this.summarizeEvaluation(c);if(0===e)return[];const f=e/d.length,g=d.filter(b=>0<b.excellent||0<b.good||0<b.ordinary||0<b.bad||0<b.abandoned),h=g.map(c=>Object.assign({},c,{score:this.calculateScore(c,b,f),rank:0})),i=h.sort((b,c)=>c.score-b.score);return i.forEach((c,a)=>c.rank=a+1),i}async add(f,a,b){const{app:c}=this,d=await c.mysql.query("INSERT INTO evaluation (station, date, excellent, good, ordinary, bad, abandoned) VALUES (?, ?, ?, ?, ?, ?, ?)",[f,a,b.excellent,b.good,b.ordinary,b.bad,b.abandoned]);return d&&1===d.affectedRows}async update(f,a,b){const{app:c}=this,d=await c.mysql.query("UPDATE evaluation SET excellent = ?, good = ?, ordinary = ?, bad = ?, abandoned = ? WHERE station = ? AND date = ?",[b.excellent,b.good,b.ordinary,b.bad,b.abandoned,f,a]);return d&&0<d.affectedRows}}exports.default=EvaluationService;