Skip to content

Instantly share code, notes, and snippets.

@pi3r0
Last active December 13, 2023 22:46
Show Gist options
  • Save pi3r0/46717a61a7e9faa7ab059860325579ea to your computer and use it in GitHub Desktop.
Save pi3r0/46717a61a7e9faa7ab059860325579ea to your computer and use it in GitHub Desktop.
secretSantaEngine
const test = [
{ name: "0", email: "0@test.com" },
{ name: "1", email: "1@test.com" },
{ name: "2", email: "2@test.com" },
{ name: "3", email: "3@test.com" },
{ name: "4", email: "4@test.com" },
{ name: "5", email: "5@test.com" },
{ name: "6", email: "6@test.com" },
{ name: "7", email: "7@test.com" },
{ name: "8", email: "8@test.com" },
{ name: "9", email: "9@test.com" },
]
interface UserProps {
name: string;
email: string;
}
type Users = User[];
class User {
private _receiveFrom: User | null = null;
private _giveTo: User | null = null;
private _pickIndex: number = 0;
constructor(readonly name: string, readonly email: string) {}
public hasAlreadyBeenPickedToReceive(): boolean { return !!this._receiveFrom };
public hasAlreadyBeenPickedToGive(): boolean { return !!this._giveTo };
public firstPicked(): boolean {
return !this._pickIndex;
}
public pickAt(): number {
return this._pickIndex;
}
public willGiveTo(user: User) {
this._giveTo = user;
return this;
}
public willReceiveFrom(user: User) {
this._receiveFrom = user;
this._pickIndex = this._giveTo ? this._pickIndex : user.pickAt() + 1;
return this;
}
public itsme(email: string): boolean {
return this.email === email
}
public toString(): string {
return `${this.name} : Give to ${this._giveTo?.name}, Receive from ${this._receiveFrom?.name}, picked in ${this._pickIndex}`;
}
// Autonomous
public pick(users: Users): User | null {
const eligibleReceiver = users.filter((user) => !user.itsme(this.email) && !user.hasAlreadyBeenPickedToGive() );
const nextReceiver = eligibleReceiver.length > 0 ? eligibleReceiver[Math.floor(Math.random() * eligibleReceiver.length)] : users.filter((user) => user.hasAlreadyBeenPickedToGive() && !user.hasAlreadyBeenPickedToReceive() )[0];
this._giveTo = nextReceiver;
nextReceiver.willReceiveFrom(this);
console.log(this.toString());
return !nextReceiver.hasAlreadyBeenPickedToGive() ? nextReceiver.pick(users) : null;
}
public willGiveToToString(): string {
return `${this.name} -> ` + (this._giveTo && this._giveTo.firstPicked() ? `${this._giveTo.name}` : `${this._giveTo?.willGiveToToString()}` );
}
public willReceivedFromToString(): string {
return `${this.name} <- ` + (this._receiveFrom && this._receiveFrom.firstPicked() ? `${this._receiveFrom.name}` : `${this._receiveFrom?.willReceivedFromToString()}` );
}
}
class SecretSantaEngine {
users: Users;
constructor(readonly userProps: UserProps[]) {
this.users = userProps.map((value) => new User(value.name, value.name))
}
launch() {
let receiver = this.users[Math.floor(Math.random() * this.users.length)];
do {
const nextReceiver = this.nextReceiver(receiver.email);
receiver.willGiveTo(nextReceiver);
console.log(receiver.toString());
receiver = nextReceiver.willReceiveFrom(receiver);
} while (!receiver.hasAlreadyBeenPickedToGive())
return this.toString();
}
private ellegibleReceivers(forUserEmail: string | null): Users {
return this.users.filter((user) => !(forUserEmail ? user.itsme(forUserEmail) : true) && !user.hasAlreadyBeenPickedToGive() );
}
private nextReceiver(forUserEmail: string): User {
const eligibleReceivers = this.ellegibleReceivers(forUserEmail);
return eligibleReceivers.length > 0 ? eligibleReceivers[Math.floor(Math.random() * eligibleReceivers.length)] : this.users.filter((user) => user.hasAlreadyBeenPickedToGive() && !user.hasAlreadyBeenPickedToReceive() )[0];
}
toString(): string | unknown {
const firstPicked = this.users.filter((user) => user.firstPicked())[0];
return firstPicked ? { giveWay: firstPicked.willGiveToToString(), receivedWay: firstPicked.willReceivedFromToString() } : 'Launch first';
}
}
const aSecretSantaEngine = new SecretSantaEngine(test);
console.log(aSecretSantaEngine.launch())
@pi3r0
Copy link
Author

pi3r0 commented Dec 13, 2023

To run it : tsc secret_santa.ts && node secret_santa.js

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment