A simple lucky draw program
Life is so hard, sometimes you want to give your friend a surprise to make their life more colorful. 🎨
Therefore, I highly recommend my DIY lucky draw’s idea to you. HAHA. 🖌️
Rules
Point Level & Gift Pool
Firstly, I classify the fabbit points into 4 types, similar to LOL ranking:
- bronze
- silver
- golden
- diamond
They can be used to redeem different levels of gift. The gift pool is shown as the screenshots below as an example:
It varies from a cup of milk tea, to an iPhone 13, so-called ‘Gift-diversity’.
Lucky Draw Quota
The lucky draw quota acts like a motivation
you encourge your friends to do something for you.
For example, if you want them to share their Windows 10 OS RCE - Price For Love
program with you, you can give them 20 lucky-draw quota to achieve this goal.
A great deal, right? 😁
Demo
Use the Ultimate vimrc to improve C++ coding experience
Source Code
Github Repo
draw.cpp
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<cstdlib>
#include<utility>
#include<vector>
#include<random>
#include<fstream>
#include<string>
#include<map>
//the following are UBUNTU/LINUX, and MacOS ONLY terminal color codes.
#define RESET "\033[0m"
#define RED "\033[31m"
#define BLUE "\033[34m"
#define BOLDYELLOW "\033[1m\033[33m"
#define BOLDCYAN "\033[1m\033[36m"
//Storage
#define POINT_STORAGE_FILE "wallet.txt"
#define DELIMITER ":"
typedef double probability;
typedef std::string name;
using namespace std;
map<name, int> mapPointBox = {{"bronze", 0}, {"silver", 0}, {"golden", 0}, {"diamond", 0}};
struct Prize {
string name;
double value; // the price of the prize
int point_level;
int redeem_points; // how many points can redeem this prize
};
int getRandomNumberInRange(int min, int max){
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(min, max);
return dis(gen);
}
bool inRange(int low, int high, int x) {
return (low <= x && x < high);
}
vector< pair<name, probability> > getRanges(vector< pair<name, probability> > pointDrawProbability) {
vector< pair<name, probability> > ranges;
double accumulate = 0;
for (auto i = pointDrawProbability.begin(); i != pointDrawProbability.end(); ++i) {
accumulate += i->second;
pair<name, probability> newPair = std::make_pair(i->first, accumulate);
ranges.push_back(std::move(newPair));
}
return ranges;
}
string drawOnce(vector< pair<name, probability> > pointBox) {
double random = double(getRandomNumberInRange(0, 99)) / 100;
for (auto i = pointBox.begin(); i != pointBox.end(); ++i) {
if (random < i->second) {
return i->first;
}
}
return "Error";
}
void printPrize(name prize) {
if (prize == "bronze") {
std::cout << RED << "bronze " << RESET << "fabbit point" << std::endl;
} else if (prize == "silver") {
std::cout << BLUE << "silver " << RESET << "fabbit point" << std::endl;
} else if (prize == "golden") {
std::cout << BOLDYELLOW << "Yay! golden fabbit point" << RESET << std::endl;
} else if (prize == "diamond") {
std::cout << BOLDCYAN << "🐰: Wow!!! You got a " << prize << " fabbit point! 😍" << RESET << std::endl;
}
}
auto draw_n_times(int times_to_draw, vector< pair<name, probability> > pointDrawRange) {
for (int i = 0; i < times_to_draw; ++i) {
name prize = drawOnce(pointDrawRange);
printPrize(prize);
mapPointBox[prize] += 1;
}
}
void readFromFile() {
string line;
ifstream myfile (POINT_STORAGE_FILE);
if (!myfile.is_open()) {
cout << "Unable to open file";
return ;
}
std::cout << "Your current points in the 🐰's wallet:" << std::endl;
std::cout << "======================" << std::endl;
while (myfile) {
string s;
if (!getline(myfile, s)) break;
name prize = s.substr(0, s.find(DELIMITER));
int number = stoi(s.substr(s.find(DELIMITER) + 2, s.length() - 1));
std::cout << prize << " points: " << number << std::endl;
mapPointBox[prize] = number;
}
std::cout << "======================" << std::endl;
myfile.close();
}
void writeToFile() {
ofstream myfile;
myfile.open(POINT_STORAGE_FILE);
for (auto i = mapPointBox.begin(); i != mapPointBox.end(); ++i) {
myfile << i->first << ": " << i->second << "\n";
}
myfile.close();
}
int main(){
// Initialization
// TO-DO: use a file to initialize pointBox
std::cout << BOLDYELLOW << "\nWelcome to fabbit's lucky draw program.\n" << RESET << std::endl;
vector< pair<name, probability> > pointDrawProbability;
pointDrawProbability.push_back(std::make_pair("bronze", 0.6));
pointDrawProbability.push_back(std::make_pair("silver", 0.3));
pointDrawProbability.push_back(std::make_pair("golden", 0.09));
pointDrawProbability.push_back(std::make_pair("diamond", 0.01));
readFromFile();
// get input
int times_to_draw;
std::cout << "Please input your remaining lucky draw quota today:" << std::endl;
std::cin >> times_to_draw;
std::cout << "Start the game..." << std::endl;
// start game
auto pointDrawRange = getRanges(pointDrawProbability);
draw_n_times(times_to_draw, pointDrawRange);
writeToFile();
std::cout << "======================" << std::endl;
std::cout << "Congratulations! Data Saved to wallet." << std::endl;
return 0;
}
To compile:
$ g++ draw.cpp -std=c++14 -o draw
$ ./draw
Thoughts
Due to the time constraint in this lovely Saturday evening, I haven’t polished this simple program much, will enable more features in the future.
Thanks for participating this lucky draw game in your brain.