点击查看Vue编辑器说明文档

分数计算器edit icon

|
|
Fork(复制)
|
|
作者:
cup11

👉 新版编辑器已上线,点击进行体验吧!

BUG反馈
嵌入
设置
下载
<template>
格式化
支持Emmet,输入 p 后按 Tab键试试吧!
            
            <header>
  <h1>评分</h1>
</header>
<main>
  <section>
    <h2>睡眠 (30%) <span class="score">{{sleepScore.total}}分</span></h2>
    <div>
      <span>时长:</span>
      <input type="number" min="0" max="24" step="1" v-model="sleep.duration.hour">
      <span>:</span>
      <input type="number" min="0" max="60" step="1" v-model="sleep.duration.minute">
      <span class="score">{{sleepScore.duration}}分</span>
    </div>
    <div>
      <span>入睡:</span>
      <input type="number" min="0" max="24" step="1" v-model="sleep.bedtime.hour">
      <span>:</span>
      <input type="number" min="0" max="60" step="1" v-model="sleep.bedtime.minute">
      <span class="score">{{sleepScore.bedtime}}分</span>
    </div>
    <div>
      <span>手表评分:</span>
      <input type="number" min="0" step="1" v-model="sleep.watchScore">
      <span>分</span>
      <span class="score">{{sleepScore.watchScore}}分</span>
    </div>
  </section>
  <section>
    <h2>习惯 (15%) <span class="score">{{habitScore.total}}分</span></h2>
    <div>
      <span>Anki:</span>
      <input type="number" min="0" step="1" v-model="habit.anki">
      <span>张</span>
      <span class="score">{{habitScore.anki}}分</span>
    </div>
    <div>
      <span>背单词:复习</span>
      <input type="number" min="0" step="1" v-model="habit.words.review">
      <span>个,新学</span>
      <input type="number" min="0" step="1" v-model="habit.words.learn">
      <span>个</span>
      <span class="score">{{habitScore.words}}分</span>
    </div>
  </section>
  <section>
    <h2>作业 (40%) <span class="score">{{homeworkScore.total}}分</span></h2>
    <div>
      <span>开始:</span>
      <span>+</span>
      <input type="number" min="0" step="1" v-model="homework.start">
      <span>min</span>
      <span class="score">{{homeworkScore.start}}分</span>
    </div>
    <div>
      <span>有效时间:</span>
      <input type="number" min="0" step="1" v-model="homework.validTime.hour">
      <span>:</span>
      <input type="number" min="0" step="1" v-model="homework.validTime.minute">
      <span class="score">{{homeworkScore.validTime}}分</span>
    </div>
    <div>
      <span>结束:</span>
      <span>+</span>
      <input type="number" min="0" step="1" v-model="homework.end">
      <span>min</span>
    </div>
    <div>
      <span>总作业量:</span>
      <input type="number" min="0" step="1" v-model="homework.total">
      <span>min</span>
    </div>
    <div>
      <span>效率:{{(homeworkScore.efficiencyValue * 100).toFixed(2)}}%</span>
      <span class="score">{{homeworkScore.efficiency}}分</span>
    </div>
  </section>
  <section>
    <h2>卫生 (5%) <span class="score">{{bathScore}}分</span></h2>
    <div>
      <span>距离上一次洗澡:</span>
      <input type="number" min="0" step="1" v-model="bath.days">
      <span>天</span>
    </div>
    <div>
      <span>季节</span>
      <select v-model="bath.season">
        <option value="summer">夏</option>
        <option value="spring">春/秋</option>
        <option value="winter">冬</option>
      </select>
    </div>
  </section>
  <section>
    <h2>运动 (10%) <span class="score">{{sportScore}}分</span></h2>
    <div>
      <span>中高强度时长:</span>
      <input type="number" min="0" step="1" v-model="sport.workout">
      <span>min</span>
    </div>
    <div>
      <span>1000m</span>
      <input type="number" min="0" step="1" v-model="sport.oneKilo.minute">
      <span>:</span>
      <input type="number" min="0" step="1" v-model="sport.oneKilo.second">
    </div>
  </section>
  <section>
    <h2>总评</h2>
    <div class="score">{{total.score}} 分</div>
    <div class="score">{{total.level}} 级</div>
  </section>
</main>
        
<style>
格式化
            
            body {
  text-align: center;
}

input[type="number"] {
  width: 2.5rem;
  margin: 0.25rem 0.5rem;
  text-align: right;
}

.score {
  color: purple;
  margin-left: 1rem;
  font-weight: bold;
}

h2 > .score {
  font-size: 1.25rem;
  color: blue;
}

section > .score {
  font-size: 1.5rem;
  color: darkorange;
}

body {
  padding: 3rem 0;
}
        
<script setup>
格式化
            
            // 示例代码
import { reactive, computed, watch } from "vue";

const storageReactive = (key, obj) => {
  const storageData = localStorage.getItem(`SC_${key}`);
  const result = reactive(storageData ? JSON.parse(storageData) : obj);
  watch(() => result, newObj => {
    localStorage.setItem(`SC_${key}`, JSON.stringify(newObj));
  }, { immediate: true, deep: true });
  return result;
};

const sleep = storageReactive("sleep", {
  duration: {
    hour: 3,
    minute: 0,
  },
  bedtime: {
    hour: 24,
    minute: 0,
  },
  watchScore: 50,
});

const habit = storageReactive("habit", {
  anki: 0,
  words: {
    review: 0,
    learn: 0,
  }
});

const homework = storageReactive("homework", {
  start: 180,
  end: 360,
  validTime: {
    hour: 0,
    minute: 0,
  },
  total: 30,
});

const bath = storageReactive("bath", {
  days: 7,
  season: "spring",
});

const sport = storageReactive("sport", {
  workout: 0,
  oneKilo: {
    minute: 8,
    second: 0,
  },
});

function linear(x, points, upK) {
  for (let i in points) {
    const point = points[i]
    const [target, score] = point;
    if (x <= target) {
      if (parseInt(i) === 0) {
        return score;
      }
      const [prevTarget, prevScore] = points[i - 1];
      return Math.round((x - prevTarget) / (target - prevTarget) * (score - prevScore) + prevScore);
    }
  }
  const [target, score] = points[points.length - 1];
  return Math.round(score + (x - target) * upK);
}

const sleepScore = computed(() => {
  const duration = linear(sleep.duration.hour + sleep.duration.minute / 60, [[3, 30], [4.5, 60], [6, 90], [7.5, 100]], 0);
  const bedtime = linear((sleep.bedtime.hour + sleep.bedtime.minute / 60 + 8) % 24, [[6.5, 100], [7.5, 80], [8.5, 60], [10.5, 0]], 0);
  const watchScore = linear(sleep.watchScore, [[35, 0], [85, 100]], 2);
  const total = Math.round(duration * 0.2 + bedtime * 0.4 + watchScore * 0.4);
  return {
    duration,
    bedtime, 
    watchScore, 
    total,
  };
});

const habitScore = computed(() => {
  const anki = linear(habit.anki, [[0, 40], [20, 60], [40, 80], [80, 100]], 0.5);
  const words = linear(habit.words.review + habit.words.learn * 3, [[0, 40], [20, 70], [40, 90], [60, 100]], 1);
  const total = Math.round(anki * 0.5 + words * 0.5);
  return {
    anki,
    words,
    total,
  }
});

const homeworkScore = computed(() => {
  const start = linear(homework.start, [[0, 140], [40, 100], [80, 60], [120, 0]], 0);
  const validTime = linear(homework.validTime.hour * 60 + homework.validTime.minute, [[0, 30], [60, 60], [120, 90], [180, 100]], 0.1);
  const efficiencyValue = homework.total / (homework.end - homework.start);
  const efficiency = linear(efficiencyValue, [[0.2, 0], [0.5, 60], [0.8, 90], [0.95, 100]], 100);
  const total = Math.round(start * 0.4 + validTime * 0.2 + efficiency * 0.4);

  return {
    start,
    validTime,
    efficiencyValue,
    efficiency,
    total,
  }
});

const bathScore = computed(() => {
  const points = bath.season === "winter" ? [
    [0, 100], [2, 90], [5, 60], [8, 0]] : (bath.season === "spring" ? [
    [0, 100], [1, 95], [2, 85], [5, 40], [7, 0]
    ] : [[0, 100], [2, 80], [5, 0]]);
  const total = linear(bath.days, points, 0);
  return total;
});

const sportScore = computed(() => {
  const workout = linear(sport.workout, [[0, 30], [10, 60], [25, 90], [35, 100]], 2);
  const oneKilo = linear(sport.oneKilo.minute * 60 + sport.oneKilo.second, [
    [180, 200], [270, 120], [300, 100], [360, 60], [480, 0]
  ], 0);
  return Math.round(Math.pow(Math.pow(workout, 4) + Math.pow(oneKilo, 4), 0.25));
});

const total = computed(() => {
  const score = Math.round(sleepScore.value.total * 0.3 + habitScore.value.total * 0.15 + homeworkScore.value.total * 0.4 + bathScore.value * 0.05 + sportScore.value * 0.1);
  const levelMap = [
    [99, "U+"], [97, "U"], [95, "S+"], [93, "S"], [90, "A+"], [87, "A"], [84, "B+"],
    [80, "B"], [76, "B-"], [72, "C+"], [66, "C"], [60, "C-"], [53, "D+"], [45, "D"],
    [30, "E"]
  ];
  const level = levelMap.find(([threshold]) => score >= threshold)?.[1] || 'F';
  return {
    score,
    level,
  };
})



        
预览
控制台