1
0
Fork 0
forked from Simnation/Main
This commit is contained in:
Nordi98 2025-08-12 20:30:24 +02:00
parent 57069485d5
commit 8d5055a73d
1412 changed files with 5583 additions and 0 deletions

View file

@ -0,0 +1,78 @@
local QBCore = exports['qb-core']:GetCoreObject()
local doorbellCooldowns = {}
-- Benachrichtigung empfangen
RegisterNetEvent('qb-doorbell:client:receiveNotification', function(message, senderName)
lib.notify({
title = 'Klingel',
description = message .. '\nVon: ' .. senderName,
type = 'inform',
duration = 8000,
position = 'top'
})
end)
-- Klingel-Funktion
local function RingDoorbell(doorbellData)
local currentTime = GetGameTimer()
-- Cooldown Check
if doorbellCooldowns[doorbellData.id] and
(currentTime - doorbellCooldowns[doorbellData.id]) < Config.CooldownTime then
local remainingTime = math.ceil((Config.CooldownTime - (currentTime - doorbellCooldowns[doorbellData.id])) / 1000)
lib.notify({
title = 'Klingel',
description = 'Du musst noch ' .. remainingTime .. ' Sekunden warten!',
type = 'error',
duration = 3000
})
return
end
-- Cooldown setzen
doorbellCooldowns[doorbellData.id] = currentTime
-- Server Event triggern
TriggerServerEvent('qb-doorbell:server:ringDoorbell', doorbellData)
lib.notify({
title = 'Klingel',
description = 'Du hast geklingelt!',
type = 'success',
duration = 3000
})
end
-- Klingel-Interaktionen erstellen
local function CreateDoorbellInteractions()
for _, doorbell in pairs(Config.Doorbells) do
local point = lib.points.new({
coords = doorbell.bellCoords,
distance = Config.InteractionDistance,
doorbell = doorbell
})
function point:onEnter()
lib.showTextUI('[E] ' .. self.doorbell.label, {
position = "left-center",
icon = 'bell'
})
end
function point:onExit()
lib.hideTextUI()
end
function point:nearby()
if IsControlJustPressed(0, 38) then -- E Key
RingDoorbell(self.doorbell)
end
end
end
end
-- Initialisierung
CreateThread(function()
Wait(1000)
CreateDoorbellInteractions()
end)

View file

@ -0,0 +1,65 @@
Config = {}
Config.InteractionDistance = 2.0 -- Distanz zum Klingeln
Config.CooldownTime = 5000 -- Cooldown in ms zwischen Klingeln
-- Klingel-Konfigurationen
Config.Doorbells = {
-- Beispiel 1: Polizeistation
{
id = 1,
label = "Polizeistation Klingel",
-- Koordinate wo man klingeln kann
bellCoords = vector3(441.0, -981.0, 30.7),
-- Benachrichtigungs-Einstellungen
notification = {
coords = vector3(441.0, -975.0, 30.7), -- Wo die Benachrichtigung empfangen wird
radius = 50.0, -- Umkreis in dem man die Benachrichtigung bekommt
requireJob = true, -- Job erforderlich?
allowedJobs = {"police", "sheriff"}, -- Erlaubte Jobs
message = "Jemand klingelt an der Polizeistation!"
}
},
-- Beispiel 2: Krankenhaus
{
id = 2,
label = "Krankenhaus Empfang",
bellCoords = vector3(-449.0, -340.0, 34.5),
notification = {
coords = vector3(-440.0, -340.0, 34.5),
radius = 30.0,
requireJob = true,
allowedJobs = {"ambulance", "doctor"},
message = "Patient wartet am Empfang!"
}
},
-- Beispiel 3: Öffentliche Klingel (ohne Job-Anforderung)
{
id = 3,
label = "Rathaus Klingel",
bellCoords = vector3(-544.0, -204.0, 38.2),
notification = {
coords = vector3(-540.0, -200.0, 38.2),
radius = 25.0,
requireJob = false, -- Keine Job-Anforderung
allowedJobs = {}, -- Leer da keine Jobs erforderlich
message = "Jemand benötigt Hilfe am Rathaus!"
}
},
-- Beispiel 4: Mechaniker
{
id = 4,
label = "Werkstatt Klingel",
bellCoords = vector3(-347.0, -133.0, 39.0),
notification = {
coords = vector3(-350.0, -130.0, 39.0),
radius = 40.0,
requireJob = true,
allowedJobs = {"mechanic", "tuner"},
message = "Kunde wartet in der Werkstatt!"
}
}
}

View file

@ -0,0 +1,24 @@
fx_version 'cerulean'
game 'gta5'
author 'Duck'
description 'Job Klingel'
version '1.0.0'
shared_scripts {
'@ox_lib/init.lua',
'config.lua'
}
client_scripts {
'client.lua'
}
server_scripts {
'server.lua'
}
dependencies {
'qb-core',
'ox_lib'
}

View file

@ -0,0 +1,16 @@
##############################
####################################
##### # # ##### # #
# ## # # # # #
# ## # # # ### ---DUCK SCRIPTS
# ## # # # # #
##### ### ##### # #
####################################
##############################
## Dieses Script ist NUR für Private Zwecke erstellt wurden & darf NUR auf SimNation RP verwendet werden!
## Es handelt sich hierbei um ein QB Script!

View file

@ -0,0 +1,59 @@
local QBCore = exports['qb-core']:GetCoreObject()
-- Klingel Event Handler
RegisterNetEvent('qb-doorbell:server:ringDoorbell', function(doorbellData)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if not Player then return end
local senderName = Player.PlayerData.charinfo.firstname .. " " .. Player.PlayerData.charinfo.lastname
-- Alle Spieler durchgehen
local players = QBCore.Functions.GetPlayers()
local notificationsSent = 0
for _, playerId in pairs(players) do
local targetPlayer = QBCore.Functions.GetPlayer(playerId)
if targetPlayer then
local targetCoords = GetEntityCoords(GetPlayerPed(playerId))
local distance = #(targetCoords - doorbellData.notification.coords)
-- Prüfen ob Spieler im Radius ist
if distance <= doorbellData.notification.radius then
local canReceive = false
-- Job-Prüfung
if doorbellData.notification.requireJob then
-- Prüfen ob Spieler einen der erlaubten Jobs hat
for _, allowedJob in pairs(doorbellData.notification.allowedJobs) do
if targetPlayer.PlayerData.job.name == allowedJob then
canReceive = true
break
end
end
else
-- Keine Job-Anforderung, jeder kann Benachrichtigung erhalten
canReceive = true
end
-- Benachrichtigung senden
if canReceive then
TriggerClientEvent('qb-doorbell:client:receiveNotification', playerId,
doorbellData.notification.message, senderName)
notificationsSent = notificationsSent + 1
end
end
end
end
-- Feedback an den Klingelnden wenn niemand erreicht wurde
if notificationsSent == 0 then
TriggerClientEvent('ox_lib:notify', src, {
title = 'Klingel',
description = 'Niemand scheint in der Nähe zu sein...',
type = 'error',
duration = 4000
})
end
end)

View file

@ -0,0 +1,205 @@
HUD = {}
local cfg = cfg
local targetPlayer = nil
--------------------FUNCTIONS--------------------
-- Toggle display
function HUD:SetLidarDisplayState(state)
SendNUIMessage({ action = "SetLidarDisplayState", state = state })
end
-- Set ADS mode
function HUD:SetDisplayMode(mode)
SendNUIMessage({ action = "SetDisplayMode", mode = mode })
end
-- Move & Resize
function HUD:ResizeOnScreenDisplay(reset)
reset = reset or false
if reset then
SendNUIMessage({ action = "SendResizeAndMove", reset = reset })
else
SendNUIMessage({ action = "SendResizeAndMove" })
SetNuiFocus(true, true)
end
end
-- Setter for SFX vars
function HUD:SendConfigData()
SendNUIMessage({
action = "SetConfigVars",
clockSFX = cfg.clockSFX,
selfTestSFX = cfg.selfTestSFX,
imgurApiKey = cfg.imgurApiKey,
discordApiKey = cfg.discordWebhook,
recordLimit = cfg.loggingSelectLimit,
version = GetResourceMetadata(GetCurrentResourceName(), 'version', 0),
name = GetCurrentResourceName(),
metric = cfg.useMetric,
theme = HIST:GetTabletTheme(),
osdStyle = HIST:GetOsdStyle(),
})
end
-- Send Lidar return data
function HUD:SendLidarUpdate(speed, range, towards)
if type(speed) == 'number' or type(range) == 'number' then
speed = string.format('%.0f', speed)
range = string.format("%.1f", range)
end
SendNUIMessage({
action = "SendClockData",
speed = speed,
range = range,
towards = towards,
})
end
-- Send Lidar return data
function HUD:SendPeersDisplayData(dataTable)
SendNUIMessage({
action = "SendPeersDisplayData",
speed = dataTable.speed,
range = dataTable.range,
arrow = dataTable.arrow,
elapsedTime = dataTable.elapsedTime,
battery = dataTable.battery,
})
end
-- Send clear lidar strings
function HUD:ClearLidarDisplay()
self:SendLidarUpdate('---', '----', -1)
end
-- Send change scope style
function HUD:ChangeSightStyle()
SendNUIMessage({
action = "scopestyle",
})
end
-- Sends loading bar for random time
function HUD:DisplaySelfTest()
local wait1 = math.random(10,50)*100
local wait2 = math.random(150,750)
local wait3 = math.random(7,10)*100
CreateThread(function()
HUD:SetSelfTestState(false, false)
Wait(1000)
SendNUIMessage({action = "SendSelfTestProgress", progress = "[|||________________]" })
Wait(wait1)
SendNUIMessage({ action = "SendSelfTestProgress", progress = "[||||||||___________]" })
Wait(wait2)
SendNUIMessage({ action = "SendSelfTestProgress", progress = "[||||||||||||||||||_]" })
Wait(wait3)
SendNUIMessage({ action = "SendSelfTestProgress", progress = "[|||||||||||||||||||]", stopTimer = true })
Wait(100)
SendNUIMessage({ action = "SendSelfTestProgress", progress = "EEPROM = PASS" })
Wait(2000)
SendNUIMessage({ action = "SendSelfTestProgress", progress = "TIMER = PASS" })
Wait(2000)
SendNUIMessage({ action = "SendSelfTestProgress", progress = "CHECKSUM = PASS" })
Wait(2500)
HUD:SetSelfTestState(true, true)
end)
end
-- Handles initialization of self-test state
function HUD:SetSelfTestState(state, playSound)
selfTestState = state
SendNUIMessage({ action = "SetSelfTestState", state = selfTestState, sound = playSound })
if state then
HIST:SetSelfTestTimestamp()
HUD:ClearLidarDisplay()
end
end
function HUD:SetHistoryState(state)
SendNUIMessage({ action = "SetHistoryState", state = state })
end
function HUD:SetHistoryData(index, data)
SendNUIMessage({ action = "SendHistoryData", counter = index, time = data.time, clock = data.clock })
end
function HUD:SendDatabaseRecords(dataTable)
SendNUIMessage({ action = "SendDatabaseRecords", name = GetPlayerName(PlayerId()), table = json.encode(dataTable), time = string.format("%s:%s:00", GetClockHours(), GetClockMinutes()) })
end
function HUD:SetTabletState(state)
SetNuiFocus(state, state)
SendNUIMessage({ action = "SetTabletState", state = state })
end
function HUD:GetCurrentDisplayData(closestPlayer)
targetPlayer = closestPlayer
SendNUIMessage({ action = "GetCurrentDisplayData" })
end
function HUD:SendBatteryPercentage(percentage)
percentage = percentage or math.random(1,100)
local bars = 4
-- default full charge do not need to send NUI
if percentage > 40 then
return
end
-- 60%-4, 25%-3, 10%-2, 5%-1
if percentage < 40 and percentage > 15 then
bars = 3
elseif percentage < 15 and percentage > 5 then
bars = 2
else
bars = 1
end
SendNUIMessage({ action = "SendBatteryAmount", bars = bars })
end
--[[Callback for JS -> LUA to close tablet on html button]]
RegisterNUICallback('CloseTablet', function(cb)
HUD:SetTabletState(false)
end )
--[[Callback for JS -> LUA to save current theme option]]
RegisterNUICallback('SendTheme', function(data, cb)
HIST:SaveTabletTheme(data)
end )
--[[Callback for JS -> LUA to get display information back]]
RegisterNUICallback('ReturnCurrentDisplayData', function(data, cb)
TriggerServerEvent('prolaser4:SendDisplayData', targetPlayer, data)
end )
--[[Callback for JS -> LUA to get OSD position and scale]]
RegisterNUICallback('ReturnOsdScaleAndPos', function(data, cb)
HIST:SaveOsdStyle(data)
SetNuiFocus(false, false)
end )
--[[Callback for JS -> LUA Notify of resolution change and temporary position reset]]
RegisterNUICallback('ResolutionChange', function(data, cb)
if data.restore then
HUD:ShowNotification("~y~Info~w~: resolution changed, restoring old ProLaser4 position.")
else
HUD:ShowNotification("~y~Info~w~: resolution changed, resetting ProLaser4 position temporarily.")
end
end )
--On screen GTA V notification
function HUD:ShowNotification(text)
SetNotificationTextEntry('STRING')
AddTextComponentString(text)
DrawNotification(false, true)
end
function HUD:DisplayControlHint(hint)
SetTextComponentFormat('STRING')
if hint == 'fpADS' then
AddTextComponentString('~INPUT_AIM~ Toggle ADS\n~INPUT_LOOK_BEHIND~ Change Scope Style')
DisplayHelpTextFromStringLabel(0, 0, 0, 5000)
elseif hint == 'moveOSD' then
AddTextEntry('prolaser4_move', '~INPUT_LOOK_LR~ Move\n~INPUT_WEAPON_WHEEL_PREV~ Resize Larger\n~INPUT_WEAPON_WHEEL_NEXT~ Resize Smaller')
AddTextComponentSubstringTextLabel('prolaser4_move')
DisplayHelpTextFromStringLabel(0, 0, 0, 7000)
end
end

View file

@ -0,0 +1,99 @@
@import url("https://bootswatch.com/3/cyborg/bootstrap.min.css");
body {
color: black;
}
#tablet{
color: white;
background-color: #080808 !important;
}
.table-btn{
width: 90%;
height: 73%;
background-color: #424242;
border: 1px solid #424242;
}
.table-btn:hover {
background-color: #282828;
border: 1px solid #232323;
}
/* PRINT VIEW */
#view-record > * {
background-color: white;
color: black;
}
.print-view-print-btn {
background-color: #606060;
}
.print-view-print-btn:hover{
background-color: #424242;
}
.fa-print {
color: white !important;
}
/* PRINT VIEW PRINT RESULT DIALOG */
#print-result-dialog {
background-color: black;
color: white;
border: rgb(39, 39, 39) 0.5vh solid;
}
h6 {
color: white;
}
.btn-group > * {
border: unset !important;
}
.btn-check:checked + .btn-outline-primary {
background-color: #1a62ae;
color: #fff;
}
.btn-check:not(:checked) + .btn-outline-primary {
color: unset;
background: #424242;
}
.map-controls-container {
border-left: 2px #4a4a4a solid;
}
.map-controls-label {
color: white !important;
}
.btn-outline-primary:hover {
background-color: #282828 !important;
}
.legend-container {
background-color: rgb(40 40 40 / 70%);
box-shadow: 0 0 5px #00000073;
color: white;
}
.legend-container.hidden {
display: none;
}
.legend-container:hover {
background-color: rgb(50 50 50) !important;
}
.marker-label {
color: black !important;
}
#loading-dialog {
background: #323131;
}

View file

@ -0,0 +1,227 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="style.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.13.2/css/jquery.dataTables.min.css"/>
<link rel="stylesheet" id="theme" href=""/>
<link href="https://fonts.googleapis.com/css2?family=Roboto&display=swap" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js" type="text/javascript"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ho+j7jyWK8fNQe+A12Hb8AhRq26LrZ/JpcUGGOn+Y7RsweNrtN/tE3MoK7ZeZDyx" crossorigin="anonymous"></script>
<script type="text/javascript" src="https://cdn.datatables.net/1.13.2/js/jquery.dataTables.min.js"></script>
<script src="https://kit.fontawesome.com/dca78979b0.js" crossorigin="anonymous"></script>
<script src="https://html2canvas.hertzen.com/dist/html2canvas.min.js"></script>
<script src="lidar.js" type="text/javascript"></script>
</head>
<body>
<div id="hud">
<p id='range-hud'>WAIT</</p>
<p id='speed-hud'>TESTING</p>
</div>
<div id="laser-gun">
<img src="textures/screen.png" style="position: absolute; top: 34%; right: 18%; width: 408px; height: 103px; transform-origin: center; offset-anchor: center; z-index: 2; opacity: 0.15;">
<img src="textures/grid.png" style="position: absolute; top: 32%; right: 17%; width: 403px; height: 103px; offset-anchor: center; z-index: 1; opacity: 0.5; margin: 6px;">
<div id="self-test-container">
<p style="font-size: 30px;">SELF TEST IN PROGRESS</p>
<p id="self-test-progress" style="line-height: 1.5;">[___________________]</p>
<p id="self-test-timer">00:00</p>
</div>
<div id="lidar-home" style="display: none;">
<div id="left">
<img id="arrowup" src="textures/arrow.png" style="width: 47px; grid-area: 1 / 1 / auto / auto; margin: 0px -6px;">
<img id="arrowdown" src="textures/arrow.png" style="width: 47px; grid-area: 1 / 1 / auto / auto; margin: 24px -10px -15px; transform: rotate(180deg);">
<p id="speed">---</p>
<p id="unit">mph</p>
</div>
<div id="vertical-div"></div>
<div id="right">
<p id="range">----ft</p>
<p id="timer"></p>
<img id="lock" src="textures/lock.png" style="width: 135px; float: right; grid-row: 1 / auto; position: absolute; bottom: -28%; right: -16%;">
<img id="battery" src="textures/battery4.png" style="width: 163px; float: right; bottom: -71%; right: -23%; position: absolute; margin: 0px;">
</div>
</div>
<div id="history-container">
<p id="counter" style="text-align: center; width: 20%; margin-top: 2%";></p>
<p id="history-header" style="font-size: 1.9em; text-align: center; margin-top: -7.3%;">Recalled Events</p>
<p id="timestamp" style="line-height: 1.7; margin-left: 3%;"></p>
<p id="clock" style="line-height: 1; margin-left: 3%;"></p>
</div>
</div>
<div id="print-result-dialog-container" class="centered-container" style="z-index: 11;">
<div id="print-result-dialog">
<div class='dialog-body'>
<div class="bg-primary fixedhd dialog-header">
<button id="print-dialog-close" class="btn btn-danger print-view-close-btn"><i class="fas fa-sign-out-alt"></i></button>
</div>
<p id="dialog-msg" class="center" style="text-shadow: unset;margin-bottom: 0px;">Uploaded Successfully</p>
<p id="url-display-imgur" class="center" style="text-shadow: unset; margin-bottom: 0px; margin-top: 10px;"></p>
<p id="url-display-discord" class="center" style="margin-bottom: 15px; text-shadow: unset;"></p>
<button id="copy-button" class="btn btn-success dialog-button">Copy to Clipboard</button>
</div>
</div>
</div>
<div id="view-record-container" class="centered-container" style="z-index: 10;">
<div id="view-record">
<div class="bg-primary fixedhd print-view-header">
<button id="print-view-close" class="btn btn-danger mt-3 mr-5 btn-lg print-view-close-btn"><i class="fas fa-sign-out-alt"></i></button>
<button id="print-view-print" class="btn btn-light mt-3 mr-5 btn-lg print-view-print-btn" style="float: left;"><i class="fa-sharp fa-solid fa-print"></i></button>
</div>
<center><img style="height: 45px;margin-bottom: 20px;" src="textures/prolaser-logo-black.png" ></center>
<p style="text-align: center;margin-bottom: 2px;font-weight:bold; text-shadow: unset;">SPEED EVENT RECORD</p>
<hr>
<table>
<tbody>
<tr>
<th class="left" style="padding-left: 5px; font-size: 11pt;" colspan="6">Instrument Details</th>
</tr>
<tr>
<th class="left" style="background: unset; min-width: 130px;">Device:</th>
<td class="left" style="width: 625px;">ProLaser 4</td>
</tr>
<tr>
<th class="left no-background">Serial:</th>
<td id="serial" class="left"></td>
</tr>
<tr>
<th class="left no-background">User:</th>
<td id="playerName" class="left"></td>
</tr>
<tr>
<th class="left" style="background: unset;">Self Test Performed:</th>
<td id="self-test-time" class="left"></td>
<th class="center" style="min-width: 75px;">EEPROM</th>
<th class="center" style="min-width: 75px;">TIMER</th>
<th class="center" style="min-width: 75px;">CHECKSUM</th>
</tr>
<tr>
<td>
&nbsp;
</td>
<td>
&nbsp;
</td>
<td class="center testResult"></td>
<td class="center testResult"></td>
<td class="center testResult"></td>
</tr>
<tr>
<th class="left no-background">Wavelength:</th>
<td id="playerName" class="left">904nm +/- 10nm</td>
</tr>
<tr>
<th class="left no-background">Speed Accurancy:</th>
<td id="playerName" class="left">+/- 1mph</td>
</tr>
<tr>
<th class="left no-background">Range Accurancy:</th>
<td id="playerName" class="left">+/-6”</td>
</tr>
</tbody>
</table>
<br>
<table style="margin-top:25px; width:100%;">
<tbody>
<tr>
<th class="left" style="padding-left: 5px; font-size: 11pt;" colspan="5">Lidar Records</th>
</tr>
<tr>
<th class="center small-font-size">RID</th>
<th class="center small-font-size">Date/Time</th>
<th class="center small-font-size">Est. Speed</th>
<th class="center small-font-size">Est. Distance</th>
<th class="center small-font-size">Est. Location</th>
</tr>
<tr>
<td id="recID" class="small-font-size"></td>
<td id="recDate" class="small-font-size"></td>
<td id="recSpeed" class="small-font-size"></td>
<td id="recRange" class="small-font-size"></td>
<td id="recStreet" class="small-font-size" style="min-width:200px"></td>
</tr>
</tbody>
</table>
<table style="margin-top:25px;width:100%;">
<tbody>
<tr>
<th style="text-align: left; padding-left: 5px; font-size: 11pt;" colspan="1">Estimated Geolocation</th>
</tr>
</tbody>
</table>
<div id='print-map' style="margin-top: 20px; width: 400px; height: 275px;"></div>
<div class="footer-container">
<hr>
<div class="footer">
<p class="left" style="padding-left:0; text-shadow: unset;">Luxart Engineering Inc.</p>
<p class="center" style="text-shadow: unset;">1 / 1</p>
<p id='print-footer-date' class="right" style="text-shadow: unset;"></p>
</div>
</div>
</div>
</div>
<div id="tablet-container" class="centered-container">
<div id="tablet">
<div id="loading-dialog-container" class="centered-container">
<div id="loading-dialog">
<p id="loading-header" style="text-shadow: unset;margin: 18px 0 10px 18px;font-size: 20px;font-weight: bolder;">Please Wait..</p>
<p id="loading-message" style="text-shadow: unset;margin: 0 0 0 18px;font-size: 15px;"><i class="fa fa-spinner fa-spin" aria-hidden="true"></i> Processing Records..</p>
</div>
</div>
<div class="bg-primary fixedhd" style="background-color: rgb(24 24 24) !important; margin: -1px;">
<div class="map-controls-container" >
<div class="map-controls">
<p class="map-controls-label" style="grid-column: 1/3;">Map Markers:</p>
<p class="map-controls-label">Legend:</p>
<div class="btn-group d-flex" style="justify-content: right; margin-right: 5px;" role="group">
<input type="radio" class="btn-check" name="btn-group-page" id="btn-this-page" autocomplete="off" checked>
<label class="btn btn-outline-primary rounded-start" for="btn-this-page" style="min-width: 88px">This Page</label>
<input type="radio" class="btn-check" name="btn-group-page" id="btn-all-pages" autocomplete="off">
<label class="btn btn-outline-primary" style="min-width: 88px" for="btn-all-pages">All</label>
</div>
<div class="btn-group d-flex" style="justify-content: left; margin-left: 5px;" role="group">
<input type="radio" class="btn-check" name="btn-group-player" id="btn-own" autocomplete="off">
<label class="btn btn-outline-primary rounded-start" for="btn-own" style="min-width: 88px">Own</label>
<input type="radio" class="btn-check" name="btn-group-player" id="btn-all-players" autocomplete="off" checked>
<label class="btn btn-outline-primary" style="min-width: 88px" for="btn-all-players">All Players</label>
</div>
<div class="btn-group d-flex" role="group">
<input type="radio" class="btn-check" name="btn-group-legend" id="btn-legend-off" autocomplete="off">
<label class="btn btn-outline-primary rounded-start" for="btn-legend-off">Off</label>
<input type="radio" class="btn-check" name="btn-group-legend" id="btn-legend-on" autocomplete="off" checked>
<label class="btn btn-outline-primary" for="btn-legend-on">On</label>
</div>
</div>
</div>
<button id="tablet-close" class="btn btn-danger mt-3 mr-5 btn-lg"><i class="fa-sharp fa-solid fa-xmark"></i></button>
<button id="toggle-theme" class="btn mt-3 mr-5 btn-lg" style="color: white;"><i class="fa-solid fa-circle-half-stroke"><span id="theme-text"> D</span></i></button>
<p id="date-time"></p>
<img style="margin: 15px; height: 30px;" src="textures/prolaser-logo.png" >
</div>
<div id="clock-table-container">
<table id="clock-table" class="table table-striped table-bordered" cellspacing="0" width="100%">
<thead>
<tr>
<th class="rid">Record<br>ID</th>
<th class="timestamp">Timestamp</th>
<th class="speed">Speed<br>(mph)</th>
<th class="distance">Distance<br>(feet)</th>
<th class="player">User</th>
<th class="street">Street</th>
<th class="mapping">Map</th>
<th class="print">Print</th>
</tr>
</thead>
<tbody id="tBody">
</tbody>
</table>
</div>
<div id="map"><span class="loading">loading tiles...</span></div>
<p id="tablet-version"></p>
</div>
</div>
</body>
</html>

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,758 @@
@font-face {
font-family: 'EnvyCodeR';
src: url('./fonts/EnvyCodeR-Bold.ttf');
}
@font-face {
font-family: 'SmallLcd';
src: url('./fonts/SmallLcdSignRegular-eLvm.ttf');
}
p {
text-shadow: 0 0 12px #1bff00ab, 0 0 44px #10ff00;
}
b > a:focus {
outline: none !important;
}
body {
margin: 0;
padding: 0;
overflow: hidden;
height: 100%;
width: 100%;
background: unset !important;
line-height: unset !important;
font-family: 'Roboto', sans-serif !important;
}
#self-test-container {
display: block;
position: absolute;
top: 34%;
left: 18%;
width: 64%;
height: 26%;
}
#self-test-container > p {
font-family: "EnvyCodeR";
font-weight: bolder;
color: #b6ff9e;
text-align: center;
font-size: 24px;
margin: 0;
}
#hud {
display: grid;
grid-row: 1/2;
position: absolute;
background: url(textures/hud_sight.png);
background-repeat: no-repeat;
width: 100%;
height: 100%;
left: 0px;
top: 0px;
background-size: cover;
background-position: bottom;
}
#range-hud{
font-family: 'SmallLcd';
color: #d0db21;
margin: 24px 0px -1px;
grid-column: 1;
grid-row: 1;
text-align: center;
margin-top: 30px;
position: relative;
top: 72%;
font-size: 48px;
font-weight: 100;
text-shadow: 3px 2px 0px rgb(251 12 12 / 20%), 0px -2px 1px rgb(49 251 12 / 50%), -1px 1px 1px rgb(0 0 0 / 50%);
}
#speed-hud{
font-family: 'SmallLcd';
color: #d0db21;
grid-column: 1;
grid-row: 2;
text-align: center;
position: relative;
font-weight: 100;
font-size: 48px;
margin-left: -22px;
top: 15%;
text-shadow: 3px 2px 0px rgb(251 12 12 / 20%), 0px -2px 1px rgb(49 251 12 / 50%), -1px 1px 1px rgb(0 0 0 / 50%);
}
#left {
display: grid;
grid-row: 1/2;
float: left;
position: absolute;
left: 19.5%;
top: 33%;
margin: 0px 0px 0px 0px;
padding: 0px;
width: 22%;
height: 27%;
}
#left > p {
text-shadow: rgb(27 255 0 / 78%) 0px 0px 12px, rgb(16 255 0 / 50%) 0px 0px 44px;
}
#unit {
position: relative;
font-size: 36px;
color: #b6ff9e;
font-family: 'ENVYCODER';
grid-row: 2;
grid-column: 2;
margin: 0px 20px 0px 0px;
text-align: right;
}
#speed {
font-family: 'ENVYCODER';
font-weight: bolder;
font-size: 64px;
color: #b6ff9e;
text-align: right;
grid-column: 2;
grid-row: 1;
margin: -4px 0px -19px 0px;
}
#right {
display: grid;
grid-column: 1/2;
grid-row: 1/2;
position: absolute;
float: right;
top: 33%;
left: 45%;
width: 37%;
height: 26%;
}
#right > p {
text-shadow: rgb(27 255 0 / 78%) 0px 0px 12px, rgb(16 255 0 / 50%) 0px 0px 44px;
}
#range {
font-family: "EnvyCodeR";
font-weight: bolder;
font-size: 30px;
color: #b6ff9e;
margin: 4px 0px -26px 0px;
grid-column: 1;
grid-row: 1;
}
#timer {
top: 29%;
font-size: 21px;
color: #b6ff9e;
font-family: 'ENVYCODER';
margin: -13px 0px 0px 13px;
grid-row: 2;
}
#vertical-div {
left: 42%;
top: 27%;
width: 0.5%;
height: 23%;
background-color: #b6ff9e;
padding: 0px;
position: absolute;
margin: 32px 0px 0px 0px;
box-shadow: rgb(27 255 0 / 78%) 0px 0px 12px, rgb(16 255 0 / 50%) 0px 0px 44px;
}
#laser-gun {
display: none;
position: absolute;
height: 389px;
width: 634px;
bottom: 2%;
margin-bottom: 0%;
background: url("textures/lidar.png");
background-size: contain;
transform: scale(0.65);
transform-origin: bottom;
left: 60%;
cursor: move;
z-index: 1;
user-select: none;
}
#top-container {
display: block;
position: absolute;
width: 42%;
height: 14%;
left: 29%;
top: 14.3%;
}
#top-container > button {
width: 20%;
height: 100%;
background: unset;
cursor: pointer;
}
#bottom-container {
display: block;
position: absolute;
width: 69%;
height: 16%;
left: 16.8%;
top: 66%;
}
#bottom-container > button {
width: 20%;
height: 100%;
background: unset;
cursor: pointer;
margin-right: 1.4vh;
}
#history-container {
display: block;
position: absolute;
top: 34%;
left: 18%;
width: 64%;
height: 26%;
}
#history-container > p {
font-family: "EnvyCodeR";
font-weight: bolder;
font-size: 1.5em;
margin: 0;
color: #b6ff9e;
text-align: left;
line-height: unset;
}
.blink{
animation: blinker 1s steps(1, jump-start) infinite;
}
@keyframes blinker {
50% {
opacity: 0;
}
}
/* TABLET STYLES */
a {
text-align: center;
}
#tablet{
background-color: rgb(255, 255, 255);
border: rgb(39, 39, 39) 1.5vh solid;
border-radius: 20px;
width: 82vw;
height: 46vw;
max-height: 1080px;
max-width: 1920px;
box-shadow: 0 0 20px 0px #000000ad;
z-index: 2;
}
#map {
position: absolute;
opacity: 0.01;
width:1126.69px;
height:600px;
}
#map > span.loading {
display: block;
text-align: center;
font: 300 italic 72px/400px "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", sans-serif;
}
#tablet-version {
display: inline-block;
position: relative;
/* float: left; */
bottom: 0%;
width: 100%;
/* margin-right: -100%; */
text-shadow: unset;
text-align: center;
color: rgb(92 92 92);
font-size: 1vh;
font-weight: bolder;
line-height: 1.9vh;
}
#clock-table-container {
position: relative;
float: left;
width: 60%;
height: 34vw;
max-height: 850px;
padding: 15px;
}
.dropdown-menu {
min-width: 130px !important;
}
.dataTables_filter{
width: 100%;
}
.table td, .table th {
height: 12px;
line-height: 12px !important;
vertical-align: middle !important;
text-align: center !important;
white-space: nowrap;
}
.rid, .speed, .range {
padding: 5px !important;
}
.speed {
font-weight: bold !important;
}
.mapping, .print {
width: 7%;
max-width: 90px;
padding: 0 !important;
}
.table-btn{
width: 90%;
height: 73%;
border-radius: 4px;
background-color: #fff;
border: 1px solid #ccc;
}
.table-btn:hover{
background-color: #e6e6e6;
border: 1px solid #adadad;
}
.centered-container {
display: flex;
position: absolute;
width: 100%;
height: 100%;
justify-content: center;
align-items: center;
}
/* PRINT VIEW */
#view-record{
width: 7in;
height: 9.1in;
margin: auto;
padding: 0.4in;
background-color: rgb(255, 255, 255);
border: rgb(66 66 66) 0.5vh solid;
border-radius: 8px;
font-family: 'Roboto';
box-shadow: 0px 0px 24px #00000082;
}
#view-record > hr {
margin-top: 0px !important;
margin-bottom: 20px !important;
border: 0;
border-top: 1px solid #b9b9b9 !important;
}
.footer-container > hr {
margin-bottom: 5px;
border-top: 1px solid #b9b9b9;
}
td {
width: 200px;
text-align: center !important;
}
#view-record > table {
text-align: center !important;
border-spacing: 3px !important;
border-collapse: separate !important;
font-size: 13px !important;
table-layout: auto !important;
}
#print-map {
width:4in !important;
height:3in !important;
overflow: hidden !important;
}
.print-view-header {
background-color: rgb(24 24 24) !important;
width: 6.90in !important;
height: 39px !important;
margin: -0.41in -0.4in 0.4in !important;
}
#view-record > table > tbody > tr > th {
background-color: rgb(237, 237, 237);
}
.footer-container{
position: relative;
color: rgb(171 171 171) !important;
}
.footer{
display: grid;
grid-template-columns: 33.33% 33.33% 33.33%;
width: 100%;
font-size: 11px;
}
.print-view-close-btn {
margin: 4px !important;
padding: 6px 11px !important;
font-size: 12px !important;
float: right;
}
.print-view-print-btn {
margin: 4px !important;
padding: 6px 11px !important;
font-size: 12px !important;
float: right;
background-color: #fff;
}
.print-view-print-btn:hover {
background-color: #e6e6e6;
}
.fa-print {
color: black;
}
.no-border {
border-width: 0 !important;
}
.left {
text-align: left !important;
padding-left: 12px;
}
.right {
text-align: right !important;
}
.center {
text-align: center !important;
}
.pass {
font-weight:bold !important;
color: green !important;
}
.no-background {
background: unset !important;
}
.small-font-size {
font-size: 12px !important;
}
/* PRINT VIEW PRINT RESULT DIALOG */
#print-result-dialog {
background-color: rgb(255, 255, 255);
padding: 0.4in 0.1in 0;
border: rgb(39, 39, 39) 0.5vh solid;
font-family: 'Roboto';
border-radius: 10px;
}
h6 {
color: black;
font-size: 16px !important;
margin: 0px !important;
}
.dialog-header {
background-color: rgb(24 24 24) !important;
width: calc(100% + 20px);
margin-left: -10px;
margin-right: -10px;
height: 38px !important;
margin-top: -39px !important;
margin-bottom: 15px !important;
}
.dialog-body {
display: grid;
align-content: center;
justify-content: center;
}
.dialog-button {
margin: 4px !important;
padding: 6px 11px !important;
font-size: 12px !important;
}
.btn-group > * {
border: 1px solid #1a62ae !important;
}
.btn-check:checked + .btn-outline-primary {
background-color: #1a62ae;
color: #fff;
}
.btn-check:not(:checked) + .btn-outline-primary {
color: #1a62ae;
}
.btn-check {
position: absolute;
clip: rect(0, 0, 0, 0);
pointer-events: none;
}
.rounded-start {
border-top-left-radius: 15px !important;
border-bottom-left-radius: 15px !important;
}
#clock-table_filter {
align-items: center;
margin-bottom: 10px;
float: left;
}
#clock-table_filter .container {
display: flex;
align-items: center;
justify-content: center;
width: calc(100% - 355px) !important;
}
.dropdown {
display: flex;
}
.dropdown-toggle {
height: 27px;
line-height: 6px;
}
.map-controls-container {
position: relative;
float: right;
display: block;
width: 40% !important;
border-left: 2px #e5e5e5 solid;
margin: 3.3% 0% 0px -39.9%;
}
.map-controls {
display: grid;
grid-template-columns: 36% 36% 17%;
grid-template-rows: 38%;
margin: 0;
}
.map-controls-label {
text-shadow: unset;
font-weight: bold;
color: black;
text-align: center;
}
#tablet-close{
float: right;
margin: 10px;
padding: 2px 19px;
font-size: 25px;
}
#toggle-theme{
float: right;
margin: 15px 12px 0px 0px;
padding: 2px 15px;
font-size: 19px;
background-color: transparent;
border: 1px solid #9b9b9b;
}
#toggle-theme:hover {
background-color: #404040;
border: 1px solid gray;
}
#theme-text {
text-shadow: none;
font-size: 10px;
}
.btn-group {
display: flex !important;
justify-content: center;
}
.btn-outline-primary {
border-radius: 0;
height: 27px !important;
line-height: 100% !important;
}
.btn-outline-primary:first-child {
border-top-left-radius: 15px;
border-bottom-left-radius: 15px;
}
.btn-outline-primary:last-child {
border-top-right-radius: 15px;
border-bottom-right-radius: 15px;
}
.btn-outline-primary:hover {
background-color: #e9ecef;
}
label[for="btn-all-pages"]:hover:after {
content: "\026A0 \0020 Performance Impact";
position: absolute;
top: 100%;
left: 50%;
transform: translate(-50%, -10%);
background-color: #212529;
color: #fff;
padding: 5px 8px;
border-radius: 3px;
font-size: 0.9em;
white-space: nowrap;
opacity: 0.9;
z-index: 3;
}
label[for="btn-all-pages"]:hover:after strong {
font-weight: bold;
color: orange;
}
label[for="btn-all-pages"]:hover:after {
color: orange;
font-weight: bold;
}
.legend-container {
background-color: rgb(255 255 255 / 70%);
border: none;
padding: 5px ;
border-radius: 5px;
box-shadow: 0 0 5px #cccccc73;
margin: 5px 0 0 5px;
}
.legend-container.hidden {
display: none;
}
.legend-container:hover {
background-color: rgb(255 255 255 / 100%);
}
.legend-item {
margin-top: 3px;
}
.legend-item > span {
margin-left: 10px;
font-weight: bold;
text-transform: uppercase;
/* color: white; */
}
.legend-item > img {
width: 10px;
}
.legend-spacer {
text-align: center;
font-weight: bold;
font-size: 12px;
}
/* Stylize the toggle button */
.toggle-button {
align-items: center;
justify-content: center;
height: 17px;
width: 167px;
background-color: rgb(255 255 255 / 70%);
color: rgb(51, 51, 51);
font-size: 12px;
font-weight: bold;
cursor: pointer;
box-shadow: rgb(0 0 0 / 30%) 0px 2px 5px;
border: none;
border-radius: 15px;
margin: 5px 0 0 5px;
}
.toggle-button:hover {
background-color: rgb(255 255 255 / 100%);
}
#loading-dialog-container {
width: 80.1vw;
height: 44.1vw;
max-height: 1036px;
max-width: 1877px;
margin: 0px 6px 0px 0px;
border-radius: 0px;
backdrop-filter: blur(3px);
z-index: 4;
}
#loading-dialog {
background: #eeeeee;
width: 3.85in !important;
height: 100px !important;
border: 10px;
border-radius: 10px;
}
#date-time {
text-shadow: unset;
float: right;
margin: 22px 22px 0px 0px;
font-size: 16px;
color: rgb(147 147 147);
cursor: none;
}
@media (max-width: 2000px) {
.map-controls-container {
margin: 4% 0% 0px -39.9% !important;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Some files were not shown because too many files have changed in this diff Show more