Я не выиграл в лотерею на годовом собрании, босс купил лотерейную программу

внешний интерфейс React.js
Я не выиграл в лотерею на годовом собрании, босс купил лотерейную программу

PK Creative празднует Китайский Новый год. Я участвую в "Творческом конкурсе Весеннего фестиваля". Подробности см.:Творческий конкурс "Праздник весны"

предисловие

Я вчера участвовал в годовом собрании компании.Очевидно, что я не получил ни одной награды.То, что "отличные сотрудники" не имеет ничего общего с нашими фронтенд инженерами, иначе я бы не писал здесь, подождите, зачем использовать "мы" здесь, [вопрос .jpg], фронтенд-инженеры не должны оцениваться как «отличные сотрудники», [пощечина.png], если небольшой партнер получает это, пожалуйста, поделитесь им в области комментариев: «Как может фронтенд -конечные инженеры будут выбраны как отличные сотрудники? 》

Поговорим о наградах компании в этом году

  • 1 место iPhone13 10
  • Второй приз Apple Watch 30
  • Три уровня Airpos 50 Ming

Специального приза нет, я чувствую, что процент побед довольно высок, так сколько людей будет участвовать? 700 человек? Почему так много людей, [вопрос.jpg], как я помню, что в компании всего около 350 человек, столько людей набрано в 2021 году? Потом я купил эту лотерейную программу.Она наверное стоила 5000+.Конкретики не помню.Интересно,а эта программа не годится для внутреннего развития? Стоит ли покупать? Забудьте об этом, не беспокойтесь об этом, давайте посмотрим, как реализуется лотерейная программа!

лотерейная программа

123.gif.gif

Ведущий сказал, что в начале нужно прокручивать экран, а ведущий останавливается, когда он его называет, это такая форма лотереи, которая всем понятна.

Призовые данные JSON

Сначала определите JSON для описания ситуации с призом.

[
  {
    name: "一等奖",
    count: 10,
    img: "https://img13.360buyimg.com/cms/jfs/t1/208697/10/617/143853/61413ae6E577772f8/fc01a7a528f9c531.png",
    time: 10,
  },
  {
    name: "二等奖",
    count: 30,
    img: "https://img11.360buyimg.com/cms/jfs/t1/203838/28/10178/146961/615ff266E8c0f9045/78bfc03faf8b1e2d.png",
    time: 5,
  },
  {
    name: "三等奖",
    count: 50,
    img: "https://img13.360buyimg.com/cms/jfs/t1/85541/32/9875/160522/5e12bfe2Ed83e51f5/934dbc9de37038f2.png",
    time: 5,
  },
];

время — количество розыгрышей, количество — количество призов

выдавать себя за пользователя

Используемый здесь знаменитый faker.js в настоящее время поддерживается сообществом.Во-первых, установите пакет

npm install @faker-js/faker -D

Создать 700 пользователей

import faker from "@faker-js/faker";
faker.setLocale("zh_CN");

const users = new Array(700).fill(null).map((item, index) => ({
    id: index + 1,
    name: faker.name.lastName() + faker.name.firstName(),
  }));

id должен быть уникальным, т.к. могут быть кейсы с одинаковым названием

JS реализует лотерею

То есть случайным образом выбрать нескольких пользователей из списка пользователей.

const randomCountUser = (list, count) => {
  let shows = [];
  for (let index = 0; index < count; index++) {
    const random = Math.floor(Math.random() * list.length);
    shows.push(list[random]);
    list[random] = list[list.length - 1];
    list.length--;
  }
  return shows;
};

image.png

  • Почему бы не использоватьsplice?

    • Большинство людей начинают думатьsplice, что является очень правильным и интуитивно понятным пониманием. Но будь остороженspliceЭто операция, которая потребляет много производительности.Если лотерейный пул большой, это, очевидно, повлияет на производительность.
  • зачем даватьlist[random]Присвоение, а затем уменьшить длину на единицу?

    • Нам нужно удалить выигравших пользователей, затем заполнить пользователей в конце массива и, наконец, уменьшить длину всего массива на единицу, чтобы в следующем раунде обхода это был совершенно новый массив, и изменения всего массива минимальны, с минимальным потреблением производительности.

Реагировать на реализацию

Создайте проект с приложением create-реагировать и настройте tailwindcss

npx create-react-app my-project
npm install -D tailwindcss postcss autoprefixernpx tailwindcss init -p

Сначала определите несколько состояний

// 当前抽几等奖奖
const [current, setCurrent] = useState(awards.length - 1);
const award = awards[current];
// 是否结束
const [over, setOver] = useState(false);
//  当前抽了几次
const [currentTime, setCurrentTime] = useState(0);
// 是的在进行中
const goingRef = useRef(false);
// 已经中奖用户,拥有用户数据过滤
const [winners, setWinners] = useState([]);
//  中奖结果输出
const [result, setResult] = useState({});
// 界面展示用户
const [showUsers, setShowUsers] = useState([]);
// 一次抽几个
const  currentNumber = award.count / award.time;

Нажмите старт, чтобы приостановить реализацию

  const toggle = () => {
    if (over) {
      return;
    }
    if (!goingRef.current) {
      if (award.count > currentWinNumber) {
        const winnerIds = winners.map((w) => w.id);
        let others = winnerIds.length
          ? users.filter((u) => !winnerIds.includes(u.id))
          : users;
        goingRef.current = setInterval(() => {
          setShowUsers(randomCountUser(others, currentNumber));
        }, 200);
      } else {
        if (current > 0) {
          setCurrentTime(0);
          setShowUsers([]);
          setCurrent(current - 1);
        } else {
          setOver(true);
        }
      }
    } else {
      clearInterval(goingRef.current);
      goingRef.current = false;
      setWinners([...winners, ...showUsers]);
      setResult((prev) => {
        let sumWinners = prev[award.name] || [];
        sumWinners = sumWinners.concat(showUsers);
        return {
          ...prev,
          [award.name]: sumWinners,
        };
      });
      setCurrentTime(currentTime + 1);
    }
  };

Использование CSS попутного ветра

использоватьgridмакетplace-items-stretchЭтот класс позволяет дочерним элементам покрывать всю область

image.png

Суммировать

Это заворачивает это, так быстро? До 100 строк кода, программа лотереи, купленная боссом, это так просто? Есть ли внутренняя квота? , Тогда давайте добавим внутреннюю квоту

как выиграть 100%,

Добавить параметры по умолчанию


const suerData={
    '一等奖':[701,702]
}

701 и 702 - это 2 пользователя, которых я добавил позже, я надеюсь, что эти 2 пользователя получат первый приз.

пользовательские крючки

На самом деле ядро ​​лотереи — это случайные числа, нам нужно только определить входные и выходные параметры, параметры в процессе лотереи нас не интересуют. Все, что мы можем извлечь, — это пользовательский хук.

войти

  • пользователи все пользователи
  • вручает все награды
  • Квота по умолчанию sureData

выход

  • переключить запуск или остановку
  • награда Текущий розыгрыш
  • showUsers Отображаемые пользователи
  • результат победный результат
const reducer = (state, payload) => ({ ...state, ...payload });

function useLottery(users, awards, sureData = {}) {
  // 是的在进行中
  const goingRef = useRef(false);
  const [state, setState] = useReducer(reducer, {
    current: awards.length - 1,
    over: false, //是否结束
    currentTime: 0, //  当前抽了几次
    winners: [], // 已经中奖用户,拥有用户数据过滤
    result: [], //  中奖结果输出
    showUsers: [], // 界面展示用户
    sure: sureData,
  });

  const { current, over, currentTime, winners, result, showUsers, sure } =
    state;

  // 当前抽几等奖奖
  const award = awards[current];

  // 一次抽几个
  const currentNumber = award.count / award.time;
  //currentWinNumber
  const currentWinNumber = currentTime * currentNumber;

  const toggle = () => {
    if (over) {
      return;
    }
    if (!goingRef.current) {
      if (award.count > currentWinNumber) {
        const winnerIds = winners.map((w) => w.id);
        let others = winnerIds.length
          ? users.filter((u) => !winnerIds.includes(u.id))
          : users;
        goingRef.current = setInterval(() => {
          setState({
            showUsers: randomCountUser(others, currentNumber),
          });
        }, 200);
      } else {
        if (current > 0) {
          setState({
            currentTime: 0,
            showUsers: [],
            current: current - 1,
          });
        } else {
          setState({
            over: true,
          });
        }
      }
    } else {
      clearInterval(goingRef.current);
      goingRef.current = false;
      // 最终显示用户,为了可以直接修改
      let finailyShowUsers = showUsers;
      let finailySureData = { ...sure };
      // 如果有内定名额逻辑
      if (Array.isArray(sure[award.name])) {
        finailyShowUsers = showUsers.map((p, index) => {
          let sureUser;
          sureUser = sure[award.name][index]
            ? users.find((u) => u.id === sure[award.name][index])
            : undefined;
          if (sureUser) {
            finailySureData[award.name] = sure[award.name].filter(
              (id) => id !== sureUser.id
            );
            return sureUser;
          } else {
            return p;
          }
        });
      }
      let sumWinners = result[award.name] || [];
      sumWinners = sumWinners.concat(finailyShowUsers);

      setState({
        winners: [...winners, ...finailyShowUsers],
        showUsers: finailyShowUsers,
        currentTime: currentTime + 1,
        sure: finailySureData,
        result: {
          ...result,
          [award.name]: sumWinners,
        },
      });
    }
  };

  return {
    toggle,
    result,
    award,
    showUsers,
  };
}

тестовое задание

использовать крючки

const { toggle, award, showUsers, result } = useLottery(users, awards, {
    三等奖: [701, 702],
  });

image.png

Опубликовать пакет npm

Конечно, мы можем опубликовать npm-пакет для этого хука.Возможно, в будущем мы разработаем мобильную страницу лотереи.Мы можем поделиться этой логикой лотереи, просто переписав часть просмотра. Перед релизом пакета этот хук нужно протестировать, здесь я использую @testing-library/react-hooks, поэтому не буду здесь вдаваться в подробности, а оставлю статью "Как тестировать react-хуки?" 》

наконец

Благодаря этой статье я узнал

  1. Опубликовать npm-пакет React Hooks
  2. Используйте действия github для автоматической публикации пакетов npm
  3. Развертывание страниц предварительного просмотра с помощью страниц github
  4. Все лотерейные программы представляют собой случайные числа.
  5. Да, может быть квота по умолчанию для программы

Лотерейная программа плюс (дополнительная квота) Я такжебесплатный подарокВсем, надеюсь, вам понравится.

Полный текст окончен, не забудьте поставить лайк 👍🏻. Я надеюсь, что эта статья будет вам полезна. Вы также можете обратиться к моим предыдущим статьям или поделиться своими мыслями и опытом в области комментариев. Добро пожаловать, чтобы вместе изучить внешний интерфейс.