This commit is contained in:
Tobias Hopp 2024-04-11 01:21:53 +02:00
parent 97caf4b30e
commit a59424171d
14 changed files with 164 additions and 82 deletions

View File

@ -19,5 +19,7 @@ export const IPCSend = (
message: IPCAnswer,
...args: any
): void => {
console.log("Sending ", message, " to " + channel);
global.mainWebContents.send(channel, message, ...args);
};

View File

@ -1,5 +1,5 @@
import {NFC} from "nfc-pcsc";
import {IPCSend} from "./IPCHandler";
import {IPCSend} from "./IPCMainHandler";
import {
IPCListenChannels,
NFCAccountCard,
@ -54,7 +54,6 @@ export default class NFCHandler {
reader.on('end', () => {
console.log(`${reader.name} device removed`);
});
});
nfc.on('error', err => {
@ -66,7 +65,7 @@ export default class NFCHandler {
fs.watchFile(path.resolve(process.cwd(), "nfc.test"), (curr, prev) => {
let contents = fs.readFileSync(path.resolve(process.cwd(), "nfc.test")).toString("utf-8");
let parsed = this.formClass("xyz", contents);
if (parsed)
if (parsed.isComplete)
IPCSend(IPCListenChannels.NFC_CARD, {status: true, data: parsed.card});
IPCSend(IPCListenChannels.NFC_RAW, {status: parsed.isComplete, data: parsed.card});
@ -82,6 +81,8 @@ export default class NFCHandler {
* @param raw
*/
public static formClass(uid: string, raw: string): formClassReturn | null {
raw = Buffer.from(raw, "base64").toString("utf-8");
/*
NFC-Card FULL

View File

@ -93,8 +93,28 @@ export interface NFCCard {
raw?: string
}
export enum AccountSymbols {
HAT= "Hut",
CAT= "Katze",
SHOE= "Schuh",
SHIP= "Kriegsschiff",
RACE_CAR = "Rennauto",
THIMBLE= "Fingerhut",
WHEELBARROW= "Schubkarre",
DOG = "Hund",
IRON = "Bügeleisen",
BATTLESHIP = "Schlachtschiff",
TOP_HAT = "Zylinder",
CANNON = "Kanone",
TREX = "T-Rex",
RUBBER_DUCK = "Gummiente",
PENGUIN = "Pinguin",
PLAYTYPUS= "Schnabeltier"
}
export interface NFCAccountCard extends NFCCard {
symbol: string,
symbol: AccountSymbols,
nickname: string,
pin: number
}
@ -144,14 +164,13 @@ export interface NFCPropertyCard extends NFCCard {
specialProperties: NFCPropertyCardSpecialProperties|"",
}
export type TaskType =
"GET_FROM_BANK"
| "GET_FROM_ALL_PLAYERS"
| "PAY_TO_BANK"
| "PAY_TO_ALL_PLAYERS"
| "PAY_FOR_PROPS"
| "ESCAPE_JAIl";
export enum TaskType {
GET_FROM_BANK= "GET_FROM_BANK", // 1 val
PAY_TO_BANK= "PAY_TO_BANK", // 1 val
PAY_TO_ALL_PLAYERS= "PAY_TO_ALL_PLAYERS", // 1 val
PAY_FOR_PROPS= "PAY_FOR_PROPS", // 2 val
ESCAPE_JAIL= "ESCAPE_JAIL" // 0 val
}
/**
* NFC Task Card
@ -161,4 +180,5 @@ export interface NFCTaskCard extends NFCCard {
type: TaskType
amount?: number,
amount2?: number
}
}

View File

@ -1,4 +1,4 @@
import {IPCHandle} from "./IPCHandler";
import {IPCHandle} from "./IPCMainHandler";
import {FunctionTest, GameRules} from "./RawConstants";
import OSHandler from "./OSHandler";
import CloudHandler from "./CloudHandler";
@ -55,9 +55,9 @@ export default class SmartMonopoly {
IPCHandle("CLOUD_CONNECT", async (e, request) => {
try {
await CloudHandler.connect();
return {status: true}
return {status: true};
} catch (e) {
return {status: false, data: e};
return {status: false, data: e.toString()};
}
});

View File

@ -9,8 +9,7 @@ contextBridge.exposeInMainWorld('api', {
request: (channel: IPCChannel, request: IPCRequest, ...args: any): Promise<IPCAnswer> => {
return ipcRenderer.invoke(channel, request, ...args);
},
receive: (channel: IPCChannel, func: (event: IpcRendererEvent, message: IPCAnswer, ...args: any) => void) => {
console.log("preload-receive called. args: ");
listen: (channel: IPCChannel, func: (event: IpcRendererEvent, message: IPCAnswer, ...args: any) => void) => {
ipcRenderer.on(channel, (event, message: IPCAnswer, ...args: any) => func(event, message, ...args));
},
})

View File

@ -6,6 +6,7 @@ import Game from "./Game";
import GameSetup from "./GameSetup";
import GameEnd from "./GameEnd";
import Setup from "./Setup";
import IPCRendererListener from "./IPCRendererListener";
const root = createRoot(document.getElementById("root"));
@ -35,6 +36,7 @@ export class App extends Component<{}, AppState> {
currentPage: PAGE.SETUP,
showWiFi: false,
}
IPCRendererListener.initialAttach();
}
toggleWiFiSettings = (state: boolean) => {

View File

@ -1,4 +1,5 @@
import {
AccountSymbols,
NFCAccountCard,
NFCCard,
NFCCardType,
@ -29,13 +30,10 @@ import {
} from "@mui/material";
type AccountValues = keyof NFCAccountCard;
type PropertyValues = keyof NFCPropertyCard;
type TaskValues = keyof NFCTaskCard;
interface CardSetupState {
validNFCCard: boolean,
NFCCardType: NFCCardType,
accountValues: { [key in AccountValues]?: string | number },
@ -54,9 +52,15 @@ export default class CardSetup extends Component<CardSetupProps, CardSetupState>
super(props);
let defaultType = NFCCardType.ACCOUNT;
let accountValues: { [key in AccountValues]?: string | number } = {};
let propertyValues: { [key in PropertyValues]?: string | number | boolean } = {};
let taskValues: { [key in TaskValues]?: string | TaskType | number } = {};
let accountValues: { [key in AccountValues]?: string | number } = {
symbol: "pleaseSelect"
};
let propertyValues: { [key in PropertyValues]?: string | number | boolean } = {
color: "pleaseSelect"
};
let taskValues: { [key in TaskValues]?: string | TaskType | number } = {
type: "pleaseSelect"
};
if (props.card) {
defaultType = props.card.cardType as NFCCardType;
@ -84,7 +88,6 @@ export default class CardSetup extends Component<CardSetupProps, CardSetupState>
}
this.state = {
validNFCCard: false,
NFCCardType: defaultType,
accountValues: accountValues,
@ -106,7 +109,7 @@ export default class CardSetup extends Component<CardSetupProps, CardSetupState>
left: '50%',
transform: 'translate(-50%, -50%)',
width: 700,
maxHeight: '80%',
maxHeight: '85%',
overflowY: 'scroll',
height: 'auto',
display: 'block',
@ -116,7 +119,7 @@ export default class CardSetup extends Component<CardSetupProps, CardSetupState>
p: 4,
};
changeAccountState(prop: AccountValues, ev: React.ChangeEvent<HTMLTextAreaElement | HTMLInputElement>, useUpperCase = false) {
changeAccountState(prop: AccountValues, ev: any, useUpperCase = false) {
this.setState(prevState => ({
...prevState,
accountValues: {
@ -147,12 +150,12 @@ export default class CardSetup extends Component<CardSetupProps, CardSetupState>
}))
}
changeTaskState(prop: TaskValues, ev: React.ChangeEvent<HTMLTextAreaElement | HTMLInputElement>) {
changeTaskState(prop: TaskValues, ev: any) {
this.setState(prevState => ({
...prevState,
taskValues: {
...prevState.taskValues,
prop: ev.target.value
[prop]: ev.target.value
}
}))
}
@ -160,12 +163,20 @@ export default class CardSetup extends Component<CardSetupProps, CardSetupState>
insertInputsPerType = () => {
if (this.state.NFCCardType == NFCCardType.ACCOUNT) {
return (<FormGroup sx={{m: 1}}>
<TextField sx={{mb: 1}}
label="Symbol"
type="text"
value={this.state.accountValues["symbol"]}
onChange={(ev) => this.changeAccountState("symbol", ev)}
/>
<InputLabel id="symbolLabel">Symbol</InputLabel>
<Select
labelId={"symbolLabel"}
sx={{mb: 1}}
onChange={(ev) => this.changeAccountState("symbol", ev)}
label="Symbol "
value={this.state.accountValues["symbol"]}
fullWidth
>
<MenuItem disabled={true} value="pleaseSelect">Bitte wählen...</MenuItem>
{Object.entries(AccountSymbols).map((ele) => (
<MenuItem key={ele[0]} value={ele[0]}>{ele[1]}</MenuItem>
))}
</Select>
<TextField sx={{mb: 1}}
label="Nickname"
type="text"
@ -320,8 +331,8 @@ export default class CardSetup extends Component<CardSetupProps, CardSetupState>
onChange={(ev) => this.changePropertyState("specialProperties", ev)}
>
<FormControlLabel value={""} control={<Radio/>} label="Keine"/>
<FormControlLabel value="UTILITY" control={<Radio/>} label="Bahnhof"/>
<FormControlLabel value="TRAINSTATION" control={<Radio/>} label="Versorgungswerk"/>
<FormControlLabel value="TRAINSTATION" control={<Radio/>} label="Bahnhof"/>
<FormControlLabel value="UTILITY" control={<Radio/>} label="Versorgungswerk"/>
<FormControlLabel value="JAIL" control={<Radio/>} label="Gefängnis"/>
</RadioGroup>
</FormControl>
@ -334,30 +345,46 @@ export default class CardSetup extends Component<CardSetupProps, CardSetupState>
}
if (this.state.NFCCardType == NFCCardType.TASK) {
/**
* type: TaskType
* amount?: number,
* amount2?: number
*/
return (<FormGroup sx={{m: 1}}>
<InputLabel id="typeLabel">Typ</InputLabel>
<Select
labelId={"typeLabel"}
sx={{mb: 1}}
onChange={(ev) => this.changeTaskState("type", ev)}
label="Typ "
value={this.state.taskValues["type"]}
fullWidth
>
<MenuItem disabled={true} value="pleaseSelect">Bitte wählen...</MenuItem>
{Object.keys(TaskType).map((tt: string) => (
<MenuItem key={tt} value={tt}>{tt}</MenuItem>
))}
</Select>
<TextField sx={{mb: 1}}
label="Symbol"
label="Betrag 1"
type="text"
value={this.state.accountValues["symbol"]}
onChange={(ev) => this.changeAccountState("symbol", ev)}
/>
<TextField sx={{mb: 1}}
label="Nickname"
type="text"
value={this.state.accountValues["nickname"]}
disabled={this.state.taskValues["type"] == "ESCAPE_JAIL"}
value={this.state.taskValues["amount"]}
onChange={(ev) => this.changeAccountState("nickname", ev)}
helperText={this.state.taskValues["type"] == "PAY_FOR_PROPS" ? "Preis pro Haus" : "Geldbetrag"}
/>
<TextField sx={{mb: 1}}
label="PIN"
label="Betrag 2"
type="number"
value={this.state.accountValues["pin"]}
disabled={this.state.taskValues["type"] != "PAY_FOR_PROPS"}
value={this.state.taskValues["amount2"]}
onChange={(ev) => this.changeAccountState("pin", ev)}
helperText={"gfs. Preis pro Hotel"}
/>
</FormGroup>)
}
return (<div>Typ selektieren um fortzufahren.</div>)
return (<div>Bitte einen Typ selektieren um fortzufahren.<br/> </div>)
}
render() {
@ -382,7 +409,7 @@ export default class CardSetup extends Component<CardSetupProps, CardSetupState>
NFC-Karte konfigurieren
</Typography>
<Typography id="transition-modal-description" sx={{mt: 2}}>
{this.state.validNFCCard ? "Es wurde eine gültige Spielkarte erkannt." : "Es wurde eine ungültige NFC-Karte erkannt."}
{this.props.validCard ? "Es wurde eine gültige Spielkarte erkannt." : "Es wurde eine ungültige NFC-Karte erkannt."}
<br/><br/>
<div>
<InputLabel id="nfcCardTypeLabel">Karten-Typ</InputLabel>
@ -397,9 +424,8 @@ export default class CardSetup extends Component<CardSetupProps, CardSetupState>
}
>
{Object.values(NFCCardType).map(e => {
return (
<MenuItem key={e} value={(e)}>{(e)}</MenuItem>
<MenuItem key={e} value={(e)}>{(e == NFCCardType.INVALID ? "Bitte wählen" : e)}</MenuItem>
)
})}

View File

@ -1,6 +1,6 @@
import {PAGE} from "./App";
import {IPCListenChannels, NFCCard} from "../RawConstants";
import IPCListener from "./IPCListener";
import IPCRendererListener from "./IPCRendererListener";
export enum GAME_STATE {
NOT_STARTED,
@ -31,8 +31,8 @@ export default class GameHandler {
static attachNFCHandler(cb: (card: NFCCard) => void)
{
IPCListener.detach(this.attachedNFCHandler);
this.attachedNFCHandler = IPCListener.attach(IPCListenChannels.NFC_CARD, (ipcMsg) => {
IPCRendererListener.detach(this.attachedNFCHandler);
this.attachedNFCHandler = IPCRendererListener.attach(IPCListenChannels.NFC_CARD, (ipcMsg) => {
if(ipcMsg.status)
cb(ipcMsg.data as NFCCard);
});
@ -40,7 +40,7 @@ export default class GameHandler {
static detachNFCHandler()
{
IPCListener.detach(this.attachedNFCHandler);
IPCRendererListener.detach(this.attachedNFCHandler);
}
static async requestPreparing(useCloud: boolean)

View File

@ -8,18 +8,17 @@ import {
Grid, ListItemAvatar,
Snackbar,
Typography,
Avatar, ListItemText, ListItem, List
Avatar, ListItemText, ListItem, List, Chip
} from "@mui/material";
import NfcIcon from '@mui/icons-material/Nfc';
import AddCardIcon from '@mui/icons-material/AddCard';
import PersonAddIcon from '@mui/icons-material/PersonAdd';
import PersonRemoveIcon from '@mui/icons-material/PersonRemove';
import ImageIcon from '@mui/icons-material/Image';
import WorkIcon from '@mui/icons-material/Work';
import BeachAccessIcon from '@mui/icons-material/BeachAccess';
import GameHandler from "./GameHandler";
import {NFCCard} from "../RawConstants";
import {Person as PersonIcon, QrCode, RemoveDone} from "@mui/icons-material";
import CloudIcon from "@mui/icons-material/Cloud";
interface GameState {
snackMsg: string,
@ -58,7 +57,7 @@ export default class GameSetup extends Component<{}, GameState> {
return <div className="gameSetup">
<Snackbar
open={!!this.state.snackMsg}
autoHideDuration={8000}
autoHideDuration={10000}
onClose={() => {
this.setState(prevState => ({
...prevState,
@ -97,35 +96,57 @@ export default class GameSetup extends Component<{}, GameState> {
</DialogActions>
</Dialog>
<Chip sx={{position: "absolute", top: "1%", right: "1%"}} onClick={() => {this.setState(prevState => ({
...prevState,
helpDialog: true
}))}}
label="?" color="info"
variant="outlined"/>
<Typography variant="h2" sx={{mb: 2}}>Wer spielt mit?</Typography>
<Grid container spacing={1}>
<Grid item xs={4}></Grid>
<Typography variant="h2" >Wer spielt mit?</Typography>
<Chip onClick={() => {this.setState(prevState => ({
...prevState,
snackMsg: "Um einen Spieler hinzuzufügen, lege eine NFC-Karte auf den leser!"
}))}}
label={<div><NfcIcon sx={{marginTop: 0.9}} className={"animationBreathe"}
color="primary"/> NFC</div>} color="secondary"
variant="outlined"/>
<Grid sx={{mt: 2}} container spacing={1}>
<Grid item xs={2}></Grid>
<Grid justifyContent="center" alignItems="center" item xs={"auto"}>
<List sx={{ width: '100%', minWidth: '40%', bgcolor: 'background.paper', border: "1px solid black", borderRadius: "5px" }}>
<List sx={{ width: '100%', minWidth: '60%', bgcolor: 'background.paper', border: "1px solid black", borderRadius: "5px" }}>
<ListItem>
<ListItemAvatar>
<Avatar>
<ImageIcon />
<PersonIcon />
</Avatar>
</ListItemAvatar>
<ListItemText primary="Photos" secondary="Jan 9, 2014" />
<ListItemText primary="Hut" secondary="Connect+ QR-Code anzeigen" onClick={() => {console.log("connect?")}}/>
<Button sx={{ml: 4}} variant="outlined" color="info">Umbenennen</Button>
<Button sx={{ml: 1}} variant="outlined" color="error">Rauswerfen</Button>
<Button disabled sx={{ml: 1}} variant="outlined" color="primary"><QrCode/></Button>
</ListItem>
<ListItem>
<ListItemAvatar>
<Avatar>
<WorkIcon />
<PersonIcon />
</Avatar>
</ListItemAvatar>
<ListItemText primary="Work" secondary="Jan 7, 2014" />
<ListItemText primary="Schubkarre" secondary="Connect+ QR-Code anzeigen" onClick={() => {}}/>
<Button sx={{ml: 4}} variant="outlined" color="info">Umbenennen</Button>
<Button sx={{ml: 1}} variant="outlined" color="error">Rauswerfen</Button>
<Button disabled sx={{ml: 1}} variant="outlined" color="primary"><QrCode/></Button>
</ListItem>
<ListItem>
<ListItemAvatar>
<Avatar>
<BeachAccessIcon />
<CloudIcon />
</Avatar>
</ListItemAvatar>
<ListItemText primary="Vacation" secondary="July 20, 2014" />
<ListItemText primary="Schuh" secondary="Connect+ verbunden" onClick={() => {}}/>
<Button sx={{ml: 4}} variant="outlined" color="info">Umbenennen</Button>
<Button sx={{ml: 1}} variant="outlined" color="error">Rauswerfen</Button>
<Button disabled sx={{ml: 1}} variant="outlined" color="primary"><QrCode/></Button>
</ListItem>
</List>
</Grid>

View File

@ -5,7 +5,7 @@ type IPCListen = {
fn: (message: IPCAnswer, ...args: any) => void,
}
export default class IPCListener {
export default class IPCRendererListener {
private static attachments: Map<number, IPCListen> = new Map<number, IPCListen>();
private static uID = 99;

4
src/web/Player.ts Normal file
View File

@ -0,0 +1,4 @@
export default class Player {
private nickname: string;
private figure: string;
}

View File

@ -29,7 +29,7 @@ import {
PropertyColor
} from "../RawConstants";
import NfcIcon from "@mui/icons-material/Nfc";
import IPCListener from "./IPCListener";
import IPCRendererListener from "./IPCRendererListener";
import CardSetup from "./CardSetup";
@ -297,19 +297,22 @@ export default class Setup extends Component<{}, InitialSetupState> {
nfcCard: card,
validCard: isComplete
}));
console.log(card);
}
private rawNFCListener: number = 0;
componentDidMount() {
this.getSettings().then();
this.rawNFCListener = IPCListener.attach(IPCListenChannels.NFC_RAW, (message) => {
this.rawNFCListener = IPCRendererListener.attach(IPCListenChannels.NFC_RAW, (message) => {
this.onNFCRawEvent(message.data, message.status);
console.log("Got an raw nfc event")
})
this.getSettings().then();
}
componentWillUnmount() {
IPCListener.detach(this.rawNFCListener);
IPCRendererListener.detach(this.rawNFCListener);
}
handleClose = () => {

View File

@ -74,13 +74,17 @@ export default class Startup extends Component<StartupProps, StartupState> {
let response = await window.api.request("CLOUD_CONNECT", {});
this.setState((prevState) => ({
...prevState,
snackErrorMsg: response.data.toString(),
snackErrorMsg: "Fehler:" + response.data.toString(),
isCloudConnected: response.status,
isConnectionIssue: !response.status,
}));
console.log(response)
return response.status;
} catch (e) {
this.setState((prevState) => ({
...prevState,
snackErrorMsg: "Ein unerwarteter Fehler ist aufgetreten.",
}));
return false;
}
}

View File

@ -12,7 +12,7 @@
}
.animationBreathe {
animation: breathing 3s ease-out infinite normal;
animation: breathing 2.5s ease-out infinite normal;
-webkit-font-smoothing: antialiased;
}
@ -25,9 +25,9 @@
}
25% {
-webkit-transform: scale(1.1);
-ms-transform: scale(1.1);
transform: scale(1.1);
-webkit-transform: scale(1.2);
-ms-transform: scale(1.2);
transform: scale(1.2);
}
80% {