* Personaler

Überprüft das Personalsoll und die Werbephasen in allen Gebäuden

目前為 2023-04-03 提交的版本,檢視 最新版本

// ==UserScript==
// @name        * Personaler
// @namespace   bos-ernie.leitstellenspiel.de
// @version     1.0.0
// @license     BSD-3-Clause
// @author      BOS-Ernie
// @description Überprüft das Personalsoll und die Werbephasen in allen Gebäuden
// @match       https://www.leitstellenspiel.de/
// @icon        https://www.google.com/s2/favicons?sz=64&domain=leitstellenspiel.de
// @run-at      document-idle
// @grant       none
// ==/UserScript==

/* global $ */

(function () {
  "use strict";

  const buildingsWithPersonal = [0, 2, 6, 9, 11, 12, 13, 18, 19, 20];

  const buildingTypePersonalCountTarget = {
    0: 250,
    2: 80,
    6: 300,
    9: 140,
    11: 215,
    12: 34,
    13: 400,
    18: 250,
    19: 300,
    20: 80,
  };

  function addStyle() {
    const style =
      ".loader{width:100px;height:100px;border-radius:100%;position:relative;margin:0 auto;top:40px;left:-2.5px}.loader span{display:inline-block;width:5px;height:20px;background-color:#c9302c}.loader span:first-child{animation:1s ease-in-out infinite grow}.loader span:nth-child(2){animation:1s ease-in-out .15s infinite grow}.loader span:nth-child(3){animation:1s ease-in-out .3s infinite grow}.loader span:nth-child(4){animation:1s ease-in-out .45s infinite grow}@keyframes grow{0%,100%{-webkit-transform:scaleY(1);-ms-transform:scaleY(1);-o-transform:scaleY(1);transform:scaleY(1)}50%{-webkit-transform:scaleY(1.8);-ms-transform:scaleY(1.8);-o-transform:scaleY(1.8);transform:scaleY(1.8)}}";

    const styleElement = document.createElement("style");
    styleElement.innerHTML = style;
    document.head.appendChild(styleElement);
  }

  function addMenuEntry() {
    const profileMenu = document.getElementById("logout_button").parentElement.parentElement;
    const divider = document.createElement("li");
    divider.setAttribute("class", "divider");
    divider.setAttribute("role", "presentation");

    profileMenu.append(divider);

    const bedIcon = document.createElement("span");
    bedIcon.setAttribute("class", "glyphicon glyphicon-user");

    const button = document.createElement("a");
    button.setAttribute("href", "javascript: void(0)");
    button.setAttribute("id", "personaler-button");
    button.append(bedIcon);
    button.append(" Personaler");
    button.addEventListener("click", buttonClick);

    const li = document.createElement("li");
    li.appendChild(button);

    profileMenu.append(li);
  }

  function addModal() {
    const modal = document.createElement("div");
    modal.className = "modal fade";
    modal.id = "personaler-modal";
    modal.setAttribute("tabindex", "-1");
    modal.setAttribute("role", "dialog");
    modal.setAttribute("aria-labelledby", "personaler-modal-label");
    modal.setAttribute("aria-hidden", "true");
    modal.style.zIndex = "5000";
    modal.innerHTML = `
<div class="modal-dialog modal-lg" role="document" style="width: 1280px;">
    <div class="modal-content">
        <div class="modal-header">
            <h1 class="modal-title" id="personaler-modal-label"><span class="glyphicon glyphicon-user" aria-hidden="true"></span> Personaler</h1>
            <button type="button" class="close" data-dismiss="modal" aria-label="Close">    
                <span aria-hidden="true">&times;</span>
            </button>
        </div>  
        <div class="modal-body" style="max-height: calc(100vh - 212px);overflow-y: auto;">
            <ul class="nav nav-tabs" role="tablist">
                <li role="presentation" class="active">
                    <a href="#tab-buildings-with-incorrect-personal-count-target" aria-controls="tab-buildings-with-incorrect-personal-count-target" role="tab" data-toggle="tab">Gebäude mit falschem Personal (Soll)</a>
                </li>
                <li role="presentation">
                    <a href="#tab-buildings-without-automatic-hiring" aria-controls="tab-buildings-without-automatic-hiring" role="tab" data-toggle="tab">Gebäude ohne automatische Werbung</a>
                </li>
            </ul>
            <div>
                <div class="tab-content">
                    <div role="tabpanel" class="tab-pane active" id="tab-buildings-with-incorrect-personal-count-target">
                        <div id="buildings-with-incorrect-personal-count-target" class="resizable">
                            <div class="row">
                                <div class="col-md-12 bg">
                                    <div class="loader">
                                        <span></span>
                                        <span></span>
                                        <span></span>
                                        <span></span>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                    <div role="tabpanel" class="tab-pane" id="tab-buildings-without-automatic-hiring">
                        <div id="buildings-without-automatic-hiring" class="resizable">
                            <div class="row">
                                <div class="col-md-12 bg">
                                    <div class="loader">
                                        <span></span>
                                        <span></span>
                                        <span></span>
                                        <span></span>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
`;
    document.body.appendChild(modal);
  }

  function buttonClick(event) {
    event.preventDefault();
    render();

    $("#personaler-modal").modal("show");
  }

  function getPersonalCountTarget(building_type) {
    return buildingTypePersonalCountTarget[building_type];
  }

  async function getBuildings() {
    if (
      !sessionStorage.aBuildings ||
      JSON.parse(sessionStorage.aBuildings).lastUpdate < new Date().getTime() - 5 * 1000 * 60
    ) {
      const buildings = await fetch("/api/buildings.json").then(response => response.json());

      try {
        sessionStorage.setItem("aBuildings", JSON.stringify({ lastUpdate: new Date().getTime(), value: buildings }));
      } catch (e) {
        return buildings;
      }
    }
    return JSON.parse(sessionStorage.aBuildings).value;
  }

  async function getBuildingsWithIncorrectPersonalCountTarget() {
    const buildings = await getBuildings();

    return buildings.filter(
      building =>
        buildingsWithPersonal.includes(building.building_type) &&
        building.personal_count_target !== getPersonalCountTarget(building.building_type),
    );
  }

  async function getBuildingsWithoutAutomaticHiring() {
    const buildings = await getBuildings();

    return buildings.filter(
      building => buildingsWithPersonal.includes(building.building_type) && building.hiring_automatic !== true,
    );
  }

  async function render() {
    const buildingsWithIncorrectPersonalCountTarget = await getBuildingsWithIncorrectPersonalCountTarget();
    if (buildingsWithIncorrectPersonalCountTarget.length > 0) {
      const tabPersonalCountTarget = document.getElementById("buildings-with-incorrect-personal-count-target");
      tabPersonalCountTarget.innerHTML = `
<table class="table table-striped table-hover">
  <thead>
    <tr>
      <th>Gebäude</th>
      <th>Ist: Personal (Soll)</th>
      <th>Soll: Personal (Soll)</th>
      </tr>
  </thead>
  <tbody>
    ${buildingsWithIncorrectPersonalCountTarget
      .map(
        building => `
    <tr>
      <td><a href="/buildings/${building.id}">${building.caption}</a></td>
      <td>${building.personal_count_target}</td>
      <td>${getPersonalCountTarget(building.building_type)}</td>
    </tr>
    `,
      )
      .join("")}
  </tbody>
</table>
`;
    } else {
      const tabPersonalCountTarget = document.getElementById("buildings-with-incorrect-personal-count-target");
      tabPersonalCountTarget.innerHTML = `
<div class="row">
  <div class="col-md-12 bg">
    <div class="alert alert-success" role="alert">
      <span class="glyphicon glyphicon-ok" aria-hidden="true"></span> Alle Gebäude haben das richtige Soll-Personal
    </div>
  </div>
</div>
`;
    }

    const tabHiring = document.getElementById("buildings-without-automatic-hiring");
    const buildingsWithoutAutomaticHiring = await getBuildingsWithoutAutomaticHiring();
    if (buildingsWithoutAutomaticHiring.length > 0) {
      tabHiring.innerHTML = `
<table class="table table-striped table-hover">
  <thead>
    <tr>
      <th>Gebäude</th>
      </tr>
  </thead>
  <tbody>
    ${buildingsWithoutAutomaticHiring
      .map(
        building => `
    <tr>
      <td><a href="/buildings/${building.id}">${building.caption}</a></td>
    </tr>
    `,
      )
      .join("")}
  </tbody>
</table>
`;
    } else {
      tabHiring.innerHTML = `
<div class="row">
  <div class="col-md-12 bg">
    <div class="alert alert-success" role="alert">
      <span class="glyphicon glyphicon-ok" aria-hidden="true"></span> Alle Gebäude haben automatische Werbung aktiviert
    </div>
  </div>
</div>
`;
    }
  }

  async function main() {
    addStyle();
    addMenuEntry();
    addModal();
  }

  main();
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址