Skip to content

Commit

Permalink
[PORT] Adds an app for tracking vendor stock from TG (#81582) (#586)
Browse files Browse the repository at this point in the history
Co-authored-by: RimiNosha <[email protected]>
  • Loading branch information
TyrantCerberus and RimiNosha authored Jun 1, 2024
1 parent 7a173d0 commit 62076e6
Show file tree
Hide file tree
Showing 10 changed files with 153 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@
starting_programs = list(
/datum/computer_file/program/shipping,
/datum/computer_file/program/robocontrol,
/datum/computer_file/program/restock_tracker,
)

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,9 @@
/datum/computer_file/program/crew_manifest,
/datum/computer_file/program/status,
/datum/computer_file/program/science,
/datum/computer_file/program/robocontrol,
/datum/computer_file/program/shipping,
/datum/computer_file/program/robocontrol,
/datum/computer_file/program/restock_tracker,
)

/**
Expand Down Expand Up @@ -251,6 +251,7 @@
starting_programs = list(
/datum/computer_file/program/shipping,
/datum/computer_file/program/robocontrol,
/datum/computer_file/program/restock_tracker,
)

/obj/item/modular_computer/pda/shaftminer
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/datum/computer_file/program/restock_tracker
filename = "restockapp"
filedesc = "Restock Tracker"
category = PROGRAM_CATEGORY_SUPL
program_icon_state = "restock"
extended_desc = "An IoT-networked app listing all official vending machines found onboard and how well-stocked they are."
requires_ntnet = TRUE
size = 4
program_icon = "cash-register"
tgui_id = "NtosRestock"

/datum/computer_file/program/restock_tracker/ui_data()
var/list/data = list()
var/list/vending_list = list()
var/id_increment = 1
for(var/obj/machinery/vending/vendor as anything in GLOB.vending_machines_to_restock)
var/stock = vendor.total_loaded_stock()
var/max_stock = vendor.total_max_stock()
if(max_stock == 0 || (stock >= max_stock))
continue
vending_list += list(list(
"name" = vendor.name,
"location" = get_area_name(vendor),
"percentage" = (stock / max_stock) * 100,
"id" = id_increment,
))
id_increment++
data["vending_list"] = vending_list
return data
24 changes: 24 additions & 0 deletions code/modules/vending/_vending.dm
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
premium = list()
*/

/// List of vending machines that players can restock, so only vending machines that are on station or don't have a unique condition.
GLOBAL_LIST_EMPTY(vending_machines_to_restock)

#define MAX_VENDING_INPUT_AMOUNT 30
/**
* # vending record datum
Expand Down Expand Up @@ -226,11 +229,14 @@
circuit.onstation = onstation //sync up the circuit so the pricing schema is carried over if it's reconstructed.
else if(circuit && (circuit.onstation != onstation)) //check if they're not the same to minimize the amount of edited values.
onstation = circuit.onstation //if it was constructed outside mapload, sync the vendor up with the circuit's var so you can't bypass price requirements by moving / reconstructing it off station.
if(onstation && !onstation_override)
GLOB.vending_machines_to_restock += src //We need to keep track of the final onstation vending machines so we can keep them restocked.

/obj/machinery/vending/Destroy()
QDEL_NULL(wires)
QDEL_NULL(coin)
QDEL_NULL(bill)
GLOB.vending_machines_to_restock -= src
return ..()

/obj/machinery/vending/can_speak()
Expand Down Expand Up @@ -535,6 +541,24 @@ GLOBAL_LIST_EMPTY(vending_products)
else
products[record.product_path] = record.amount

/**
* Returns the total amount of items in the vending machine based on the product records and premium records, but not contraband
*/
/obj/machinery/vending/proc/total_loaded_stock()
var/total = 0
for(var/datum/data/vending_product/record as anything in product_records + coin_records)
total += record.amount
return total

/**
* Returns the total amount of items in the vending machine based on the product records and premium records, but not contraband
*/
/obj/machinery/vending/proc/total_max_stock()
var/total_max = 0
for(var/datum/data/vending_product/record as anything in product_records + coin_records)
total_max += record.max_amount
return total_max

/obj/machinery/vending/crowbar_act(mob/living/user, obj/item/I)
if(!component_parts)
return FALSE
Expand Down
Binary file modified icons/obj/modular_console.dmi
Binary file not shown.
Binary file modified icons/obj/modular_laptop.dmi
Binary file not shown.
Binary file modified icons/obj/modular_pda.dmi
Binary file not shown.
1 change: 1 addition & 0 deletions tgstation.dme
Original file line number Diff line number Diff line change
Expand Up @@ -4004,6 +4004,7 @@
#include "code\modules\modular_computers\file_system\programs\powermonitor.dm"
#include "code\modules\modular_computers\file_system\programs\radar.dm"
#include "code\modules\modular_computers\file_system\programs\records.dm"
#include "code\modules\modular_computers\file_system\programs\restock_tracker.dm"
#include "code\modules\modular_computers\file_system\programs\robocontrol.dm"
#include "code\modules\modular_computers\file_system\programs\robotact.dm"
#include "code\modules\modular_computers\file_system\programs\secureye.dm"
Expand Down
12 changes: 12 additions & 0 deletions tgui/packages/tgui/interfaces/NtosRestock.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { NtosWindow } from '../layouts';
import { RestockTracker } from './RestockTracker';

export const NtosRestock = (props, context) => {
return (
<NtosWindow width={575} height={560}>
<NtosWindow.Content scrollable>
<RestockTracker />
</NtosWindow.Content>
</NtosWindow>
);
};
84 changes: 84 additions & 0 deletions tgui/packages/tgui/interfaces/RestockTracker.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { sortBy } from 'common/collections';
import { round } from 'common/math';

import { useBackend } from '../backend';
import { ProgressBar, Section, Stack } from '../components';
import { Window } from '../layouts';

export const Restock = (props, context) => {
return (
<Window width={575} height={560}>
<Window.Content scrollable>
<RestockTracker />
</Window.Content>
</Window>
);
};

type VendingMachine = {
id: string;
name: string;
location: string;
percentage: number;
};

type Data = {
vending_list: VendingMachine[];
};

export const RestockTracker = (props, context) => {
const { data } = useBackend<Data>(context);
const vending_list = sortBy((vend: VendingMachine) => vend.percentage)(
data.vending_list ?? []
);
return (
<Section fill title="Vendor Stocking Status">
<Stack vertical>
<Stack fill horizontal>
<Stack.Item bold width="30%">
Vending Name
</Stack.Item>
<Stack.Item bold width="30%">
Location
</Stack.Item>
<Stack.Item bold width="40%">
Stock %
</Stack.Item>
</Stack>
<hr />
{vending_list?.map((vend) => (
<Stack key={vend.id} fill horizontal>
<Stack.Item wrap width="30%" height="100%">
{vend.name}
</Stack.Item>
<Stack.Item wrap width="30%" height="100%">
{vend.location}
</Stack.Item>
<Stack.Item
wrap
width="40%"
textAlign={
vend.percentage > 75
? 'left'
: vend.percentage > 45
? 'right'
: 'center'
}>
<ProgressBar
value={vend.percentage}
minValue={0}
maxValue={100}
ranges={{
good: [75, 100],
average: [45, 75],
bad: [0, 45],
}}>
{round(vend.percentage, 0.01)}
</ProgressBar>
</Stack.Item>
</Stack>
))}
</Stack>
</Section>
);
};

0 comments on commit 62076e6

Please sign in to comment.