This is an automated email from the git hooks/post-receive script. New commit to branch feature/149-jugement-majoritaire in repository pollen. See https://gitlab.nuiton.org/chorem/pollen.git commit ddf81a43ec216fa8fe87a7aa1b34a6cbe64b5d50 Author: Sylvain Bavencoff <bavencoff@codelutin.com> Date: Tue Oct 10 15:24:47 2017 +0200 modification de l'écran de résultat pour la jugement majoritaire ref #149 --- pollen-services/pom.xml | 5 + .../voteCounting/VoteCountingDetailResultBean.java | 8 + .../MajorityJudgmentChoiceResultBean.java | 62 ++++++ .../MajorityJudgmentDetailResultBean.java | 58 ++++++ pollen-ui-riot-js/src/main/web/i18n/en.json | 3 + pollen-ui-riot-js/src/main/web/i18n/fr.json | 3 + .../src/main/web/tag/poll/Results.tag.html | 16 +- .../MajorityJudgmentDetailResult.tag.html | 222 +++++++++++++++++++++ 8 files changed, 374 insertions(+), 3 deletions(-) diff --git a/pollen-services/pom.xml b/pollen-services/pom.xml index 5ea31ecd..b0a1a31c 100644 --- a/pollen-services/pom.xml +++ b/pollen-services/pom.xml @@ -65,6 +65,11 @@ <artifactId>pollen-votecounting-coombs</artifactId> <version>${project.version}</version> </dependency> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>pollen-votecounting-majority-judgment</artifactId> + <version>${project.version}</version> + </dependency> <dependency> <groupId>${project.groupId}</groupId> diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/bean/voteCounting/VoteCountingDetailResultBean.java b/pollen-services/src/main/java/org/chorem/pollen/services/bean/voteCounting/VoteCountingDetailResultBean.java index e40768cb..bcbb36e0 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/bean/voteCounting/VoteCountingDetailResultBean.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/bean/voteCounting/VoteCountingDetailResultBean.java @@ -25,10 +25,12 @@ import org.chorem.pollen.services.bean.voteCounting.Coombs.CoombsDetailResultBea import org.chorem.pollen.services.bean.voteCounting.InstantRunoff.InstantRunoffDetailResultBean; import org.chorem.pollen.services.bean.voteCounting.borda.BordaDetailResultBean; import org.chorem.pollen.services.bean.voteCounting.condorcet.CondorcetDetailResultBean; +import org.chorem.pollen.services.bean.voteCounting.majorityJugment.MajorityJudgmentDetailResultBean; import org.chorem.pollen.votecounting.BordaDetailResult; import org.chorem.pollen.votecounting.CondorcetDetailResult; import org.chorem.pollen.votecounting.CoombsDetailResult; import org.chorem.pollen.votecounting.InstantRunoffDetailResult; +import org.chorem.pollen.votecounting.MajorityJudgmentDetailResult; import org.chorem.pollen.votecounting.model.VoteCountingDetailResult; /** @@ -65,6 +67,12 @@ public abstract class VoteCountingDetailResultBean { instantRunoffDetailResultBean.fromResult(InstantRunoffDetailResult.class.cast(detailResult)); bean = instantRunoffDetailResultBean; + } else if (MajorityJudgmentDetailResult.class.isInstance(detailResult)) { + + MajorityJudgmentDetailResultBean majorityJudgmentDetailResultBean = new MajorityJudgmentDetailResultBean(); + majorityJudgmentDetailResultBean.fromResult(MajorityJudgmentDetailResult.class.cast(detailResult)); + bean = majorityJudgmentDetailResultBean; + } } diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/bean/voteCounting/majorityJugment/MajorityJudgmentChoiceResultBean.java b/pollen-services/src/main/java/org/chorem/pollen/services/bean/voteCounting/majorityJugment/MajorityJudgmentChoiceResultBean.java new file mode 100644 index 00000000..ad693c9c --- /dev/null +++ b/pollen-services/src/main/java/org/chorem/pollen/services/bean/voteCounting/majorityJugment/MajorityJudgmentChoiceResultBean.java @@ -0,0 +1,62 @@ +package org.chorem.pollen.services.bean.voteCounting.majorityJugment; + +import org.chorem.pollen.persistence.entity.Choice; +import org.chorem.pollen.services.bean.PollenEntityId; +import org.chorem.pollen.votecounting.MajorityJudgmentChoiceResult; + +import java.math.BigDecimal; +import java.util.List; + +/** + * @author Sylvain Bavencoff - bavencoff@codelutin.com + */ +public class MajorityJudgmentChoiceResultBean { + + protected PollenEntityId<Choice> choiceId; + + protected List<BigDecimal> voteByGrad; + + protected int median; + + public MajorityJudgmentChoiceResultBean() { + this.choiceId = PollenEntityId.newId(Choice.class);; + } + + public void fromResult(MajorityJudgmentChoiceResult choiceResult) { + + setChoiceId(choiceResult.getChoiceId()); + setVoteByGrad(choiceResult.getVoteByGrad()); + setMedian(choiceResult.getMedian()); + + } + + public PollenEntityId<Choice> getChoiceId() { + return choiceId; + } + + public void setChoiceId(PollenEntityId<Choice> choiceId) { + this.choiceId = choiceId; + } + + public void setChoiceId(String choiceId) { + + this.choiceId.setEntityId(choiceId); + } + + public List<BigDecimal> getVoteByGrad() { + return voteByGrad; + } + + public void setVoteByGrad(List<BigDecimal> voteByGrad) { + this.voteByGrad = voteByGrad; + } + + public int getMedian() { + return median; + } + + public void setMedian(int median) { + this.median = median; + } + +} diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/bean/voteCounting/majorityJugment/MajorityJudgmentDetailResultBean.java b/pollen-services/src/main/java/org/chorem/pollen/services/bean/voteCounting/majorityJugment/MajorityJudgmentDetailResultBean.java new file mode 100644 index 00000000..60b5eda9 --- /dev/null +++ b/pollen-services/src/main/java/org/chorem/pollen/services/bean/voteCounting/majorityJugment/MajorityJudgmentDetailResultBean.java @@ -0,0 +1,58 @@ +package org.chorem.pollen.services.bean.voteCounting.majorityJugment; + +import org.chorem.pollen.services.bean.voteCounting.VoteCountingDetailResultBean; +import org.chorem.pollen.votecounting.MajorityJudgmentDetailResult; + +import java.math.BigDecimal; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author Sylvain Bavencoff - bavencoff@codelutin.com + */ +public class MajorityJudgmentDetailResultBean extends VoteCountingDetailResultBean { + + protected BigDecimal sumWeight; + + protected BigDecimal halfWeight; + + protected List<MajorityJudgmentChoiceResultBean> choiceResults; + + public void fromResult(MajorityJudgmentDetailResult result) { + + setSumWeight(result.getSumWeight()); + setHalfWeight(result.getHalfWeight()); + + setChoiceResults(result.getChoiceResults().stream() + .map(choiceResult -> { + MajorityJudgmentChoiceResultBean majorityJudgmentChoiceResultBean = new MajorityJudgmentChoiceResultBean(); + majorityJudgmentChoiceResultBean.fromResult(choiceResult); + return majorityJudgmentChoiceResultBean; + }) + .collect(Collectors.toList())); + } + + public BigDecimal getSumWeight() { + return sumWeight; + } + + public void setSumWeight(BigDecimal sumWeight) { + this.sumWeight = sumWeight; + } + + public BigDecimal getHalfWeight() { + return halfWeight; + } + + public void setHalfWeight(BigDecimal halfWeight) { + this.halfWeight = halfWeight; + } + + public List<MajorityJudgmentChoiceResultBean> getChoiceResults() { + return choiceResults; + } + + public void setChoiceResults(List<MajorityJudgmentChoiceResultBean> choiceResults) { + this.choiceResults = choiceResults; + } +} diff --git a/pollen-ui-riot-js/src/main/web/i18n/en.json b/pollen-ui-riot-js/src/main/web/i18n/en.json index 4af6687c..6cdab3dd 100644 --- a/pollen-ui-riot-js/src/main/web/i18n/en.json +++ b/pollen-ui-riot-js/src/main/web/i18n/en.json @@ -108,6 +108,9 @@ "poll_results_coombs_ranks": "Ranks", "poll_results_coombs_firstRank": "First", "poll_results_coombs_lastRank": "Last", + "poll_results_majorityJudgment_title": "Histogram Cumulative of votes by choice.", + "poll_results_majorityJudgment_oneVote": "vote", + "poll_results_majorityJudgment_manyVotes": "votes", "poll_comments_one": "Comment", "poll_comments_many": "Comments", "poll_comments_noComment": "No comment.", diff --git a/pollen-ui-riot-js/src/main/web/i18n/fr.json b/pollen-ui-riot-js/src/main/web/i18n/fr.json index 6abf5ff2..c3b3037a 100644 --- a/pollen-ui-riot-js/src/main/web/i18n/fr.json +++ b/pollen-ui-riot-js/src/main/web/i18n/fr.json @@ -108,6 +108,9 @@ "poll_results_coombs_ranks": "Rangs", "poll_results_coombs_firstRank": "1er", "poll_results_coombs_lastRank": "Der.", + "poll_results_majorityJudgment_title": "Histogramme Cumulé des votes par choix.", + "poll_results_majorityJudgment_oneVote": "vote", + "poll_results_majorityJudgment_manyVotes": "votes", "poll_comments_one": "Commentaire", "poll_comments_many": "Commentaires", "poll_comments_noComment": "Pas de commentaire.", diff --git a/pollen-ui-riot-js/src/main/web/tag/poll/Results.tag.html b/pollen-ui-riot-js/src/main/web/tag/poll/Results.tag.html index 69aad642..ddf2b46e 100644 --- a/pollen-ui-riot-js/src/main/web/tag/poll/Results.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/poll/Results.tag.html @@ -8,12 +8,12 @@ it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Affero General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. #L% @@ -23,6 +23,7 @@ require("../voteCountingType/CondorcetDetailResult.tag.html"); require("../voteCountingType/BordaDetailResult.tag.html"); require("../voteCountingType/InstantRunoffDetailResult.tag.html"); require("../voteCountingType/CoombsDetailResult.tag.html"); +require("../voteCountingType/MajorityJudgmentDetailResult.tag.html"); <Results> <div class="container" show="{loaded}"> <div if="{!poll.resultIsVisible}" @@ -41,7 +42,15 @@ require("../voteCountingType/CoombsDetailResult.tag.html"); <tbody> <tr each="{result in poll.results.scores}"> <td class="score separator-top">{result.scoreOrder + 1}</td> - <td class="votes separator-top">{result.scoreValue} {parent.__["unit_" + poll.voteCountingType + "_" + (result.scoreValue > 1 ? "many" : "one")]}</td> + <td class="votes separator-top"> + <span if={parent.poll.voteCountingType !== 8}> + {result.scoreValue} + {parent.__["unit_" + poll.voteCountingType + "_" + (result.scoreValue > 1 ? "many" : "one")]} + </span> + <span if={parent.poll.voteCountingType === 8}> + {parent.poll.voteCountingConfig.grades[result.scoreValue]} + </span> + </td> <td class="choice separator-top"> <ChoiceView choice={poll.getChoice(result.choiceId)} center="true"/> </td> @@ -52,6 +61,7 @@ require("../voteCountingType/CoombsDetailResult.tag.html"); <BordaDetailResult if={poll.voteCountingType === 5}/> <InstantRunoffDetailResult if={poll.voteCountingType === 6}/> <CoombsDetailResult if={poll.voteCountingType === 7}/> + <MajorityJudgmentDetailResult if={poll.voteCountingType === 8}/> </div> </div> diff --git a/pollen-ui-riot-js/src/main/web/tag/voteCountingType/MajorityJudgmentDetailResult.tag.html b/pollen-ui-riot-js/src/main/web/tag/voteCountingType/MajorityJudgmentDetailResult.tag.html new file mode 100644 index 00000000..41dc0342 --- /dev/null +++ b/pollen-ui-riot-js/src/main/web/tag/voteCountingType/MajorityJudgmentDetailResult.tag.html @@ -0,0 +1,222 @@ +<!-- + #%L + Pollen :: UI RiotJs + %% + Copyright (C) 2009 - 2017 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + #L% + --> +require("../poll/ChoiceView.tag.html"); +<MajorityJudgmentDetailResult> + <h3 class="c-heading">{__.title}</h3> + + <div class="legend"> + <div class="legend-item" + each={grad in getGradLegend()}> + <div class="legend-item-color" + style="background-color: {grad.color}; border-color: {grad.borderColor}"> + </div> + <div class="legend-item-label"> + {grad.grad} + </div> + </div> + </div> + + + <div class="choices"> + <div class="scale"> + <div class="yaxis separator-top"> + <div class="yaxis-values"> + <div>{poll.results.detail.sumWeight}</div> + <div>{poll.results.detail.halfWeight}</div> + <div>0</div> + </div> + <div class="yaxis-line separator-right"> + </div> + </div> + <div class="xaxis separator-top "> + </div> + </div> + <div each={choice in poll.choices} class="choice"> + <div class="histogramme"> + <div class="median separator-top"></div> + <div class="bars"> + <div class="bar" + each={bar in getBars(choice)} + title={bar.title} + style="flex-grow: {bar.nbVotes}; background-color: {bar.color}; border-color: {bar.borderColor}"> + </div> + </div> + </div> + <div class="xaxis separator-top"> + <ChoiceView choice={choice}/> + </div> + </div> + + </div> + + <script type="es6"> + let session = require("../../js/Session"); + this.installBundle(session, "poll_results_majorityJudgment"); + + this.poll = require("../../js/Poll.js"); + this.onPollChange = poll => { + this.poll = poll; + this.update(); + }; + + this.getColor = (index, s, l, a) => { + let hue = 0 + 120 * index / (this.poll.voteCountingConfig.grades.length - 1); + return "hsla(" + hue + ", " + s + "%, " + l + "%, " + a + ")"; + }; + + this.getGradLegend = () => { + return this.poll.voteCountingConfig.grades.map((grad, index) => { + return { + index: index, + grad: grad, + color: this.getColor(index, 100, 50, 0.8), + borderColor: this.getColor(index, 100, 50, 1) + }; + }); + }; + + this.getBars = choice => { + let choiceResult = this.poll.results.detail.choiceResults + .find(cr => cr.choiceId === choice.id); + return choiceResult.voteByGrad.map((nbVotes, index) => { + let grad = this.poll.voteCountingConfig.grades[index]; + return { + index: index, + grad: grad, + nbVotes: nbVotes, + color: this.getColor(index, 100, 50, 0.8), + borderColor: this.getColor(index, 100, 50, 1), + title: grad + " : " + nbVotes + " " + (nbVotes === 1 ? this.__.oneVote : this.__.manyVotes) + }; + }).filter(bar => bar.nbVotes > 0); + }; + + this.listen("poll", this.onPollChange); + + </script> + + <style> + majorityjudgmentdetailresult { + width: 100%; + } + + .c-heading { + text-align: center; + } + + .legend { + display: flex; + flex-flow: row-reverse; + flex-wrap: wrap-reverse; + justify-content: flex-start; + margin: 1em 0; + } + + .legend .legend-item { + display: flex; + align-items: center; + margin: 0.2em; + width: 10em; + } + + .legend .legend-item .legend-item-color { + width: 3em; + height: 1.2em; + } + + .legend .legend-item .legend-item-label { + margin: 0 0.2em; + flex-grow: 1; + } + + + .choices { + display: flex; + justify-content: space-around; + height: 25em; + } + + .scale { + display: flex; + flex-direction: column; + align-items: flex-end; + justify-content: space-between; + } + + .scale .yaxis { + flex-grow: 1; + display: flex; + } + + .scale .yaxis .yaxis-values { + display: flex; + flex-direction: column; + align-items: flex-end; + justify-content: space-between; + } + + .scale .yaxis .yaxis-line { + width: 1em; + } + + .xaxis { + height: 1.2em; + width: 100%; + display: flex; + justify-content: center; + } + + .choice { + flex-grow: 1; + width: 1em; + display: flex; + flex-direction: column; + align-items: center; + } + + .histogramme { + position: relative; + width: 100%; + flex-grow: 1; + } + + .bars { + position: absolute; + left: 10%; + width: 80%; + height: 100%; + display: flex; + flex-direction: column; + } + + .bar { + border: solid 1px; + } + + .median { + position: absolute; + top: 50%; + width: 100%; + } + + </style> + +</MajorityJudgmentDetailResult> -- To stop receiving notification emails like this one, please contact chorem.org SCM administrator <admin+scm@chorem.org>.