initial commit

This commit is contained in:
2021-11-14 15:40:01 +01:00
commit fbfdaaccba
23 changed files with 12362 additions and 0 deletions

68
src/ItemToDisplay.ts Normal file
View File

@@ -0,0 +1,68 @@
import Item from "./types/Item"
import Side from "./types/Side"
/**
* Translates an Item to a displayable string
* @param item what item
* @param side CT or T
*/
function ItemToDisplay(item:Item, side: Side ):string {
switch (item) {
case Item.DEFAULT_PISTOL:
return side === Side.CT ? "USP-S / P2000":"Glock-18"
case Item.DUAL_BERETTAS:
return "Dual Berettas"
case Item.P250:
return "P250"
case Item.TEC_9_FIVE_SEVEN:
return side === Side.CT ? "Five-Seven / CZ75-Auto":"Tec-9 / CZ75-Auto"
case Item.DESERT_EAGLE:
return "Desert Eagle / R8 Revolver"
case Item.NOVA:
return "Nova"
case Item.XM1014:
return "XM1014"
case Item.MAG_7:
return side === Side.CT ? "MAG-7":"Sawed-Off"
case Item.M249:
return "M249"
case Item.NEGEV:
return "Negev"
case Item.MAC_10_MP9:
return side === Side.CT ? "MP9":"MAC-10"
case Item.MP7:
return "MP7 / MP5-SD"
case Item.UMP_45:
return "UMP-45"
case Item.P90:
return "P90"
case Item.PP_BIZON:
return "PP-Bizon"
case Item.FAMAS_GALIL:
return side === Side.CT ? "FAMAS":"Galil AR"
case Item.AK_47_M4:
return side === Side.CT ? "M4A4 / M4A1-S":"AK-47"
case Item.SSG_08:
return "SSG 08"
case Item.SG_554_AUG:
return side === Side.CT ? "AUG":"SG 553"
case Item.AWP:
return "AWP"
case Item.G3_SCAR:
return side === Side.CT ? "SCAR-20":"G3SG1"
case Item.MOLOTOV:
return side === Side.CT ? "Incendiary Grenade":"Molotov"
case Item.DECOY:
return "Decoy"
case Item.FLASHBANG:
return "Flashbang"
case Item.HE:
return "HE Grenade"
case Item.SMOKE:
return "Smoke"
default:
throw new Error("Item not translatable")
}
}
export default ItemToDisplay

27
src/components/App.tsx Normal file
View File

@@ -0,0 +1,27 @@
import React, { useState } from 'react';
import DeckComp from './Deck';
import Card from '../types/Card';
import CardGroup from '../types/CardGroup';
import Deck from '../types/Deck';
import Item from '../types/Item';
import Side from '../types/Side';
function App() {
const [CTDeck,setCTDeck] = useState<Deck>(new Deck(
2,new CardGroup(
2,new Card("AWE fake",false,false,Item.AWP,Item.DECOY),
new Card("M4 Flash",true,true,Item.AK_47_M4,Item.FLASHBANG)
),
new CardGroup(
3,new Card("One deag",true,false,Item.DESERT_EAGLE)
)
))
return (
<div>
<DeckComp title="CT Normal" side={Side.CT} deck={CTDeck} onChange={(newDeck)=> setCTDeck(newDeck)} />
</div>
);
}
export default App;

45
src/components/Card.tsx Normal file
View File

@@ -0,0 +1,45 @@
import React from "react"
import ItemToDisplay from "../ItemToDisplay"
import Card from "../types/Card"
import Item from "../types/Item"
import Side from "../types/Side"
import SwitchButton from "./SwitchButton"
import TextEdit from "./TextEdit"
interface Props {
card: Card
side: Side
onChange?: (newCard: Card)=>void
}
const CardComp: React.FC<Props> = ({card,side,onChange}) => {
return (
<div className="bg-blue-500 m-1 p-1">
<span className="font-bold"><TextEdit
text={card.title}
onChange={(newTitle)=>onChange?.(new Card(newTitle,card.armor,card.helmet,...card.items))}
/></span>
<div>
Helmet: <SwitchButton active={card.helmet} onChange={(to)=>onChange?.(new Card(card.title,card.armor,to,...card.items))} />
Armor: <SwitchButton active={card.armor} onChange={(to)=>onChange?.(new Card(card.title,to,card.helmet,...card.items))} />
</div>
<div className="border border-red-500">
{card.items.map((item,i)=>
<div key={i}>
{ItemToDisplay(item,side)} <span onClick={()=>{
onChange?.(new Card(card.title,card.armor,card.helmet,...card.items.filter((_,fi)=>i!==fi)))
}} className="float-right cursor-pointer" >X</span>
</div>
)}
<div className="text-center cursor-pointer" onClick={()=>{
onChange?.(new Card(card.title,card.armor,card.helmet,...card.items,Item.HE))
}} >
Add
</div>
</div>
</div>
)
}
export default CardComp

View File

@@ -0,0 +1,30 @@
import React from "react"
import CardGroup from "../types/CardGroup"
import Side from "../types/Side"
import CardComp from "./Card"
interface Props {
cardGroup: CardGroup
side: Side
onChange?: (newCardGroup: CardGroup)=>void
}
const CardGroupComp: React.FC<Props> = ({cardGroup,side,onChange}) => {
return (
<div className="bg-red-500 m-1 p-1">
Num: {cardGroup.numInDeck}
<div className="flex">
{cardGroup.cards.map((card,index) =>
<CardComp card={card} side={side} onChange={(newCard)=>{
onChange?.(new CardGroup(
cardGroup.numInDeck,
...cardGroup.cards.map((e,i)=>i===index?newCard:e))
)
}} />
)}
</div>
</div>
)
}
export default CardGroupComp

34
src/components/Deck.tsx Normal file
View File

@@ -0,0 +1,34 @@
import React from "react"
import Deck from "../types/Deck"
import Side from "../types/Side"
import CardGroupComp from "./CardGroup"
interface Props {
deck: Deck
side: Side
title: string
onChange?: (newDeck: Deck)=>void
}
const DeckComp: React.FC<Props> = ({deck,side,title,onChange}) => {
return (
<div className="bg-green-400 m-1 p-1">
<span className="font-bold">{title}</span>
{ side === Side.CT && <span> D: {deck.numDefusers} </span> }
<div className="flex">
{deck.cardGroups.map((group,index) =>
<CardGroupComp key={index} cardGroup={group} side={side}
onChange={(newGroup)=>{
onChange?.(new Deck(
deck.numDefusers,
...deck.cardGroups.map((e,i)=>i===index?newGroup:e)
))
}}
/>
)}
</div>
</div>
)
}
export default DeckComp

View File

@@ -0,0 +1,14 @@
import React from "react"
interface Props {
active: boolean
onChange: (to: boolean)=>void
}
const SwitchButton: React.FC<Props> = ({active,onChange}) => {
return (
<button onClick={()=>onChange(!active)} > {active?"YES":"NO"} </button>
)
}
export default SwitchButton

View File

@@ -0,0 +1,46 @@
import React, { useEffect, useRef, useState } from "react"
interface Props {
text: string
onChange?: (newText: string)=>void
}
const TextEdit: React.FC<Props> = ({text,onChange}) => {
const [edit,setEdit] = useState<boolean>(false)
const [inputValue,setinputValue] = useState(text)
const inputRef = useRef<HTMLInputElement>(null)
useEffect(()=>{
if (edit){
inputRef.current?.select()
}else{
if (text !== inputValue){
onChange?.(inputValue)
}
}
},[edit])
return (
<>
{!edit && <span className="cursor-pointer" onClick={()=>setEdit(true)} >{inputValue}</span>}
{edit &&
<form className="inline" onSubmit={(e)=>{
e.preventDefault()
setEdit(false)
}} >
<input
type="text"
className="bg-transparent outline-none font-bold"
value={inputValue}
onChange={(e)=>setinputValue(e.target.value)}
onBlur={()=>setEdit(false)}
ref={inputRef}
></input>
</form>
}
</>
)
}
export default TextEdit

3
src/index.css Normal file
View File

@@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

11
src/index.tsx Normal file
View File

@@ -0,0 +1,11 @@
import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/App';
import './index.css';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);

1
src/react-app-env.d.ts vendored Normal file
View File

@@ -0,0 +1 @@
/// <reference types="react-scripts" />

28
src/types/Card.ts Normal file
View File

@@ -0,0 +1,28 @@
import Item from "./Item"
class Card {
readonly title: string
readonly armor: boolean
readonly helmet: boolean
readonly items: Item[]
constructor(title: string,armor: boolean,helmet: boolean,...items:Item[]){
this.title = title
this.armor = armor
this.helmet = helmet
this.items = items
}
public toString(): string {
return `${this.title},${bToS(this.armor)},${bToS(this.helmet)},${this.items.join(",")}`
}
}
/**
* Converts a boolean to 1 for true and 0 for false
*/
function bToS(bool: boolean): string{
return bool?"1":"0"
}
export default Card

17
src/types/CardGroup.ts Normal file
View File

@@ -0,0 +1,17 @@
import Card from "./Card"
class CardGroup {
readonly numInDeck: number
readonly cards: Card[]
constructor(numInDeck: number, ...cards: Card[]) {
this.numInDeck = numInDeck
this.cards = cards
}
public toString(): string {
return `${this.numInDeck};${this.cards.map(e => e.toString()).join(";")}`
}
}
export default CardGroup

17
src/types/Deck.ts Normal file
View File

@@ -0,0 +1,17 @@
import CardGroup from "./CardGroup"
class Deck {
readonly numDefusers: number
readonly cardGroups: CardGroup[]
constructor(numDefusers: number,...cardGroups: CardGroup[]){
this.numDefusers = numDefusers
this.cardGroups = cardGroups
}
public toString(): string {
return `${this.numDefusers}|${this.cardGroups.map(e => e.toString()).join("|")}`
}
}
export default Deck

30
src/types/Item.ts Normal file
View File

@@ -0,0 +1,30 @@
enum Item {
DEFAULT_PISTOL = "secondary0",
DUAL_BERETTAS = "secondary1",
P250 = "secondary2",
TEC_9_FIVE_SEVEN = "secondary3",
DESERT_EAGLE = "secondary4",
NOVA = "heavy0",
XM1014 = "heavy1",
MAG_7 = "heavy2",
M249 = "heavy3",
NEGEV = "heavy4",
MAC_10_MP9 = "smg0",
MP7 = "smg1",
UMP_45 = "smg2",
P90 = "smg3",
PP_BIZON = "smg4",
FAMAS_GALIL = "rifle0",
AK_47_M4 = "rifle1",
SSG_08 = "rifle2",
SG_554_AUG = "rifle3",
AWP = "rifle4",
G3_SCAR = "rifle5",
MOLOTOV = "grenade0",
DECOY = "grenade1",
FLASHBANG = "grenade2",
HE = "grenade3",
SMOKE = "grenade4"
}
export default Item

6
src/types/Side.ts Normal file
View File

@@ -0,0 +1,6 @@
enum Side {
CT,
T
}
export default Side