|
- <template>
- <div v-if="isProcessing" class="progress">
- <progress>Разливаем...</progress>
- </div>
- <div v-else>
- <h2 v-if="result.state == 'error'" class="error">
- {{ result.message }}
- </h2>
- <div v-for="jam in jams" :key="jam.id">
- <h3>
- Варенье: {{ jam.id }}, всего сварено: {{ jam.vol }} мл,
- <span v-if="jam.restVol > 0" class="error"
- >осталось не розлито: {{ jam.restVol }} мл</span
- >
- <span v-else>розлито полностью</span>
- </h3>
- <ul>
- <li v-for="pot in jam.pots" :key="pot.id">
- <span
- >Банка <b>{{ pot.id }}</b> ({{ pot.vol }} мл)</span
- >
- —
- <span> залито {{ pot.jamVol }} мл</span>
- —
- <span v-if="pot.isFull"> полная</span>
- <b v-else class="error">
- недолив {{ pot.vol - pot.jamVol }} мл</b
- >
- </li>
- </ul>
- </div>
- <div v-if="emptyPots.length > 0">
- <hr>
- <h4>Остались пустые банки:</h4>
- <ul>
- <li v-for="pot in emptyPots" :key="pot.id">
- <b>{{ pot.id }}</b> ({{ pot.vol }} мл)
- </li>
- </ul>
- </div>
- </div>
- </template>
-
- <script>
- import { _ } from "vue-underscore";
- export default {
- props: ["propPots", "propJams"],
- data() {
- return {
- isProcessing: false,
- pots: [],
- jams: [],
- result: { state: "initial" },
- };
- },
- mounted: function () {
- this.isProcessing = true;
-
- this.pots = _.map(this.propPots, _.clone);
- this.jams = _.map(this.propJams, _.clone);
-
- this.result = fillPots(this.pots, this.jams);
-
- // console.log("result", this.result);
- // console.log("jams", this.jams);
-
- this.isProcessing = false;
- },
- computed: {
- emptyPots: function () {
- return this.pots.filter((p) => p.jamVol === 0);
- },
- },
- };
-
- function fillPots(pots, jams) {
- prepare(pots, jams);
-
- // Сперва попытаемся разлить варенья по банкам, заполняя их по максимуму
- // Приоритет отдаем самым большим банкам, чтобы не лазать в погреб лишний раз
-
- let isDone = false;
- let isFoundSolution;
- do {
- isFoundSolution = false;
- for (const jam of jams) {
- for (const pot of pots) {
- if (!pot.isFilled && pot.vol <= jam.restVol) {
- pot.jamId = jam.id;
- pot.jamVol = Math.min(pot.vol, jam.restVol);
- pot.isFilled = true;
- pot.isFull = true;
- jam.restVol -= pot.vol;
- jam.pots.push(pot);
- isFoundSolution = true;
- break;
- }
- }
- }
- } while (!isDone && isFoundSolution);
-
- // А теперь разливаем остатки по самым маленьким из оставшихся банок
-
- isDone = true;
- for (const jam of jams) {
- if (jam.restVol > 0) {
- for (let i = pots.length - 1; i > 0; i--) {
- if (!pots[i].isFilled && pots[i].vol >= jam.restVol) {
- pots[i].jamId = jam.id;
- pots[i].jamVol = jam.restVol;
- pots[i].isFilled = true;
- pots[i].isFull = pots[i].vol === jam.restVol;
- jam.restVol = 0;
- jam.pots.push(pots[i]);
- break;
- }
- }
- if (jam.restVol !== 0) {
- isDone = false;
- }
- }
- }
-
- if (!isDone) {
- return {
- state: "error",
- message: "Не удалось разлить варенья",
- };
- }
-
- return { state: "success" };
-
- function prepare(pots, jams) {
- pots.sort(sortByVolDesc);
- jams.sort(sortByVolDesc);
-
- for (const pot of pots) {
- pot.isFilled = false;
- pot.isFull = false;
- pot.jamId = null;
- pot.jamVol = 0;
- }
-
- for (const jam of jams) {
- jam.restVol = jam.vol;
- jam.pots = [];
- }
-
- function sortByVolDesc(a, b) {
- if (a.vol > b.vol) {
- return -1;
- } else if (a.vol < b.vol) {
- return 1;
- }
- return 0;
- }
- }
- }
- </script>
-
- <style lang="scss" scoped>
- .progress {
- height: 100%;
- display: flex;
- align-items: center;
- progress {
- width: 100%;
- }
- }
- .error {
- color: orangered;
- }
- </style>
|