Last active
December 13, 2023 22:46
-
-
Save pi3r0/46717a61a7e9faa7ab059860325579ea to your computer and use it in GitHub Desktop.
secretSantaEngine
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
To run it : tsc secret_santa.ts && node secret_santa.js