mirror of https://github.com/Paoda/blue-gacha.git
feat: implement rate-up
This commit is contained in:
parent
4962ee3d79
commit
aa68942d84
|
@ -7,7 +7,7 @@ edition = "2018"
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
rand = "^0.8"
|
||||
rand = { version = "^0.8", features = ["alloc"] }
|
||||
serde = { version = "^1.0", features = ["derive"] }
|
||||
serde_json = "^1.0"
|
||||
serde_repr = "^0.1"
|
||||
|
|
183
src/banner.rs
183
src/banner.rs
|
@ -1,24 +1,29 @@
|
|||
use std::convert::TryInto;
|
||||
|
||||
use rand::{prelude::SliceRandom, Rng};
|
||||
|
||||
use crate::{
|
||||
gacha::Rarity,
|
||||
student::{self, Student},
|
||||
};
|
||||
use crate::{
|
||||
gacha::{Gacha, Recruitment},
|
||||
i18n::{I18nString, Language},
|
||||
};
|
||||
use crate::gacha::{Gacha, Rarity, Recruitment};
|
||||
use crate::i18n::{I18nString, Language};
|
||||
use crate::student::Student;
|
||||
use rand::distributions::{Distribution, WeightedIndex};
|
||||
use rand::Rng;
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
|
||||
/// Used to Construct a Banner
|
||||
#[derive(Debug, Default)]
|
||||
pub struct BannerBuilder {
|
||||
name: I18nString,
|
||||
rates: Option<Gacha>,
|
||||
gacha: Option<Gacha>,
|
||||
sparkable: Option<Vec<Student>>,
|
||||
}
|
||||
|
||||
impl BannerBuilder {
|
||||
/// Creates a new instance of a BannerBuilder
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `jpn_name` - The name of the Banner as seen in Blue Archive
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// # use ba_gacha::banner::BannerBuilder;
|
||||
/// let banner_builder = BannerBuilder::new("ピックアップ募集");
|
||||
/// ```
|
||||
pub fn new(jpn_name: &str) -> Self {
|
||||
Self {
|
||||
name: I18nString::new(jpn_name),
|
||||
|
@ -26,21 +31,58 @@ impl BannerBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
/// Adds a Translation to the internal I18nString
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `language` - The target language.
|
||||
/// * `name` - The name of the Banner in the target language.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// # use ba_gacha::banner::BannerBuilder;
|
||||
/// # use ba_gacha::i18n::Language;
|
||||
/// let banner_builder = BannerBuilder::new("ピックアップ募集")
|
||||
/// .with_name_translation(Language::English, "Focus Recruitment");
|
||||
/// ```
|
||||
pub fn with_name_translation(mut self, language: Language, name: &str) -> Self {
|
||||
self.name.update(language, name);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_rates(self, rates: &Gacha) -> Self {
|
||||
/// Adds an instance of a Gacha struct
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `gacha` - An instance of a Gacha struct
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// # use ba_gacha::gacha::GachaBuilder;
|
||||
/// # use ba_gacha::banner::BannerBuilder;
|
||||
/// let gacha = GachaBuilder::default()
|
||||
/// .with_pool(Vec::new())
|
||||
/// .finish().unwrap();
|
||||
///
|
||||
/// let banner_builder = BannerBuilder::new("ピックアップ募集")
|
||||
/// .with_gacha(&gacha);
|
||||
/// ```
|
||||
pub fn with_gacha(self, gacha: &Gacha) -> Self {
|
||||
Self {
|
||||
rates: Some(rates.to_owned()),
|
||||
gacha: Some(gacha.to_owned()),
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_sparkable_students(self, students: Vec<Student>) -> Self {
|
||||
/// Adds a vector containing all sparkable students in the current Banner
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `students` - A Vector of Students which are sparkable
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// # use ba_gacha::banner::BannerBuilder;
|
||||
pub fn with_sparkable_students(self, students: &[Student]) -> Self {
|
||||
Self {
|
||||
sparkable: Some(students),
|
||||
sparkable: Some(students.to_vec()),
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
@ -48,56 +90,99 @@ impl BannerBuilder {
|
|||
pub fn finish(self) -> Option<Banner> {
|
||||
Some(Banner {
|
||||
name: self.name,
|
||||
rates: self.rates?,
|
||||
sparkable: self.sparkable?,
|
||||
gacha: self.gacha?,
|
||||
sparkable: self.sparkable,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
enum StudentType {
|
||||
One = 1, // One Star
|
||||
Two, // Two Stars
|
||||
Three, // Three Stars
|
||||
Priority, // Rate-up Student (Presumably 3*)
|
||||
}
|
||||
|
||||
impl From<Rarity> for StudentType {
|
||||
fn from(rarity: Rarity) -> Self {
|
||||
match rarity {
|
||||
Rarity::One => Self::One,
|
||||
Rarity::Two => Self::Two,
|
||||
Rarity::Three => Self::Three,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<StudentType> for Rarity {
|
||||
type Error = &'static str;
|
||||
|
||||
fn try_from(value: StudentType) -> Result<Self, Self::Error> {
|
||||
Ok(match value {
|
||||
StudentType::One => Self::One,
|
||||
StudentType::Two => Self::Two,
|
||||
StudentType::Three => Self::Three,
|
||||
StudentType::Priority => return Err("Can not convert from Priority to Rarity"),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Banner {
|
||||
pub name: I18nString,
|
||||
rates: Gacha,
|
||||
sparkable: Vec<Student>, // FIXME: Can we safely assume this will only contain 2 studnets?
|
||||
gacha: Gacha,
|
||||
sparkable: Option<Vec<Student>>,
|
||||
}
|
||||
|
||||
impl Banner {
|
||||
fn get_random_student(&self, rarity: Rarity) -> Student {
|
||||
fn get_random_student(&self) -> Student {
|
||||
let mut rng = rand::thread_rng();
|
||||
let priority_rate = self.gacha.priority.as_ref().map_or(0, |tuple| tuple.1);
|
||||
let three_star_rate = self.gacha.get_rate(Rarity::Three) - priority_rate;
|
||||
|
||||
let mut filtered_students: Vec<&Student> = self
|
||||
.rates
|
||||
.pool
|
||||
let items: [(StudentType, usize); 4] = [
|
||||
(StudentType::One, self.gacha.get_rate(Rarity::One)),
|
||||
(StudentType::Two, self.gacha.get_rate(Rarity::Two)),
|
||||
(StudentType::Three, three_star_rate),
|
||||
(StudentType::Priority, priority_rate),
|
||||
];
|
||||
|
||||
let dist = WeightedIndex::new(items.iter().map(|item| item.1)).unwrap();
|
||||
let students = &self.gacha.pool;
|
||||
|
||||
match items[dist.sample(&mut rng)] {
|
||||
(StudentType::Priority, _) => {
|
||||
let priority_students = &self.gacha.priority.as_ref().unwrap().0;
|
||||
|
||||
let index: usize = rng.gen_range(0..priority_students.len());
|
||||
priority_students[index].clone()
|
||||
}
|
||||
(rarity, _) => {
|
||||
let students: Vec<&Student> = students
|
||||
.iter()
|
||||
.filter(|student| student.rarity == rarity.try_into().unwrap())
|
||||
.collect();
|
||||
|
||||
let index: usize = rng.gen_range(0..students.len());
|
||||
students[index].clone()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_random_student_of_rarity(&self, rarity: Rarity) -> Student {
|
||||
let students = &self.gacha.pool;
|
||||
let two_star_students: Vec<&Student> = students
|
||||
.iter()
|
||||
.filter(|student| student.rarity == rarity)
|
||||
.collect();
|
||||
|
||||
filtered_students.shuffle(&mut rng);
|
||||
let index: usize = rng.gen_range(0..filtered_students.len());
|
||||
|
||||
filtered_students[index].clone()
|
||||
}
|
||||
|
||||
fn get_random_rarity(&self) -> Rarity {
|
||||
let mut rng = rand::thread_rng();
|
||||
let random_num: usize = rng.gen_range(0..1000);
|
||||
|
||||
let one_rate = self.rates.get_rate(Rarity::One);
|
||||
let two_rate = self.rates.get_rate(Rarity::Two);
|
||||
let three_rate = self.rates.get_rate(Rarity::Three);
|
||||
|
||||
if random_num < three_rate {
|
||||
Rarity::Three
|
||||
} else if random_num < three_rate + two_rate {
|
||||
Rarity::Two
|
||||
} else {
|
||||
Rarity::One
|
||||
}
|
||||
let index = rand::thread_rng().gen_range(0..two_star_students.len());
|
||||
two_star_students[index].clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl Recruitment for Banner {
|
||||
fn roll(&self) -> Student {
|
||||
self.get_random_student(self.get_random_rarity())
|
||||
self.get_random_student()
|
||||
}
|
||||
|
||||
fn roll10(&self) -> [Student; 10] {
|
||||
|
@ -105,14 +190,14 @@ impl Recruitment for Banner {
|
|||
|
||||
// Fill students with 10 random students
|
||||
for student in students.iter_mut() {
|
||||
*student = self.get_random_student(self.get_random_rarity());
|
||||
*student = self.get_random_student()
|
||||
}
|
||||
|
||||
let two_star_present = students.iter().any(|student| student.rarity == Rarity::Two);
|
||||
|
||||
if !two_star_present {
|
||||
if students[students.len() - 1].rarity != Rarity::Three {
|
||||
students[students.len() - 1] = self.get_random_student(Rarity::Two);
|
||||
students[students.len() - 1] = self.get_random_student_of_rarity(Rarity::Two);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
32
src/gacha.rs
32
src/gacha.rs
|
@ -43,6 +43,7 @@ pub trait Recruitment {
|
|||
pub struct GachaBuilder {
|
||||
rates: Option<(usize, usize, usize)>,
|
||||
pool: Option<Vec<Student>>,
|
||||
priority: Option<(Vec<Student>, usize)>,
|
||||
}
|
||||
|
||||
impl Default for GachaBuilder {
|
||||
|
@ -50,6 +51,7 @@ impl Default for GachaBuilder {
|
|||
Self {
|
||||
rates: Some((790, 185, 25)),
|
||||
pool: Default::default(),
|
||||
priority: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -78,7 +80,7 @@ impl GachaBuilder {
|
|||
|
||||
Self {
|
||||
rates: Some((one, two, three)),
|
||||
pool: Default::default(),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,6 +105,29 @@ impl GachaBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
/// Attaches a pool of Students who have increased rates
|
||||
///
|
||||
/// # Arugments
|
||||
/// * `students` - A Vector of Students who have increased rates
|
||||
/// * `rate` - The rate of the students in the previous argument
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// # use ba_gacha::gacha::{GachaBuilder, Rarity};
|
||||
/// # use ba_gacha::student::Student;
|
||||
/// let aru = Student::new("アル", Rarity::Three);
|
||||
/// let hina = Student::new("ヒナ", Rarity::Three);
|
||||
/// let gacha_builder = GachaBuilder::new(79.0, 18.5, 2.5)
|
||||
/// .with_pool(vec![aru, hina.clone()])
|
||||
/// .with_priority(vec![hina], 3.5);
|
||||
/// ```
|
||||
pub fn with_priority(self, students: &[Student], total_rate: f32) -> Self {
|
||||
Self {
|
||||
priority: Some((students.to_vec(), (total_rate * 10.0) as usize)),
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
/// Consumes a GachaBuilder and retuns a Gacha Struct.
|
||||
///
|
||||
/// Will return `None` if the `rates` or `pool` property of
|
||||
|
@ -122,6 +147,7 @@ impl GachaBuilder {
|
|||
Some(Gacha {
|
||||
rates: self.rates?,
|
||||
pool: self.pool?,
|
||||
priority: self.priority,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -130,8 +156,10 @@ impl GachaBuilder {
|
|||
/// to randomly select a Student from the gacha pool
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct Gacha {
|
||||
pub rates: (usize, usize, usize), // One Star, Two Star, Three Star
|
||||
/// (1★, 2★, 3★)
|
||||
pub rates: (usize, usize, usize),
|
||||
pub pool: Vec<Student>,
|
||||
pub priority: Option<(Vec<Student>, usize)>,
|
||||
}
|
||||
|
||||
impl Gacha {
|
||||
|
|
18
src/i18n.rs
18
src/i18n.rs
|
@ -7,6 +7,24 @@ pub struct I18nString {
|
|||
translations: HashMap<Language, String>,
|
||||
}
|
||||
|
||||
impl PartialEq for I18nString {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.get(Language::Japanese).unwrap() == other.get(Language::Japanese).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<String> for I18nString {
|
||||
fn eq(&self, other: &String) -> bool {
|
||||
self.get(Language::Japanese).unwrap() == *other
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<&str> for I18nString {
|
||||
fn eq(&self, other: &&str) -> bool {
|
||||
self.get(Language::Japanese).unwrap() == *other
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for I18nString {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str(self.translations.get(&Language::Japanese).unwrap().as_str())
|
||||
|
|
188
src/main.rs
188
src/main.rs
|
@ -1,174 +1,46 @@
|
|||
use std::io::Write;
|
||||
|
||||
use ba_gacha::{
|
||||
banner::BannerBuilder,
|
||||
gacha::{GachaBuilder, Rarity, Recruitment},
|
||||
i18n::Language,
|
||||
student::Student,
|
||||
};
|
||||
use ba_gacha::banner::BannerBuilder;
|
||||
use ba_gacha::gacha::{GachaBuilder, Recruitment};
|
||||
use ba_gacha::i18n::Language;
|
||||
use ba_gacha::student::Student;
|
||||
use std::{fs::File, io::Read};
|
||||
|
||||
fn main() {
|
||||
// Create a Struct representing Shiroko
|
||||
let mut shiroko = Student::new("シロコ", Rarity::Three);
|
||||
shiroko.add_translation(Language::English, "Shiroko"); // Yes, this is a translation.
|
||||
let mut file = File::open("students.json").unwrap();
|
||||
let mut json = String::new();
|
||||
file.read_to_string(&mut json).unwrap();
|
||||
|
||||
// Create a Struct representing Hoshino
|
||||
let mut hoshino = Student::new("ホシノ", Rarity::Three);
|
||||
hoshino.add_translation(Language::English, "Hoshino");
|
||||
let students: Vec<Student> = serde_json::from_str(&json).unwrap();
|
||||
|
||||
// Create a Vector Containing all the Sparkable Students
|
||||
let sparkable_students = vec![shiroko, hoshino];
|
||||
let banner_students: Vec<Student> = students
|
||||
.iter()
|
||||
.filter(|student| student.name != "ノゾミ")
|
||||
.map(|student| student.clone())
|
||||
.collect();
|
||||
|
||||
let rates = GachaBuilder::new(79.0, 18.5, 2.5)
|
||||
.with_pool(pickup_banner_2021_02_11())
|
||||
let hoshino = find_student(&students, "ホシノ").unwrap();
|
||||
let shiroko = find_student(&students, "シロコ").unwrap();
|
||||
let rate_up_students = vec![shiroko, hoshino];
|
||||
|
||||
let gacha = GachaBuilder::new(79.0, 18.5, 2.5)
|
||||
.with_pool(banner_students)
|
||||
.with_priority(&rate_up_students, 0.7)
|
||||
.finish()
|
||||
.unwrap();
|
||||
|
||||
// Create the Banner Itself
|
||||
let pickup_banner = BannerBuilder::new("ピックアップ募集")
|
||||
.with_name_translation(Language::English, "Priority")
|
||||
.with_sparkable_students(sparkable_students)
|
||||
.with_rates(&rates)
|
||||
.with_name_translation(Language::English, "Rate-Up Registration")
|
||||
.with_sparkable_students(&rate_up_students)
|
||||
.with_gacha(&gacha)
|
||||
.finish()
|
||||
.unwrap();
|
||||
|
||||
// Roll Banner 1 Time
|
||||
let student = pickup_banner.roll();
|
||||
|
||||
// Roll Banner 10 Times
|
||||
let students = pickup_banner.roll10();
|
||||
|
||||
// Display Results
|
||||
println!("{} Single: {}", pickup_banner.name, student);
|
||||
println!();
|
||||
|
||||
println!("{} 10-roll:", pickup_banner.name);
|
||||
for student in students.iter() {
|
||||
println!("{}", student);
|
||||
// let student = pickup_banner.roll();
|
||||
// let students = pickup_banner.roll10();
|
||||
}
|
||||
|
||||
// let mut file = std::fs::File::create("students.json").unwrap();
|
||||
// let students = all_students();
|
||||
// let json = serde_json::to_string(&students).unwrap();
|
||||
// file.write_all(json.as_bytes()).unwrap();
|
||||
}
|
||||
|
||||
fn create_student(jpn_name: &str, eng_name: &str, rarity: Rarity) -> Student {
|
||||
let mut student = Student::new(jpn_name, rarity);
|
||||
student.add_translation(Language::English, eng_name);
|
||||
|
||||
student
|
||||
}
|
||||
|
||||
fn pickup_banner_2021_02_11() -> Vec<Student> {
|
||||
let mut test: Vec<Student> = vec![];
|
||||
|
||||
// 3 Star
|
||||
test.push(create_student("ヒナ", "Hina", Rarity::Three));
|
||||
test.push(create_student("イオリ", "Iori", Rarity::Three));
|
||||
test.push(create_student("ハルナ", "Haruna", Rarity::Three));
|
||||
test.push(create_student("イズミ", "Izumi", Rarity::Three));
|
||||
test.push(create_student("アル", "Aru", Rarity::Three));
|
||||
test.push(create_student("スミレ", "Sumire", Rarity::Three));
|
||||
test.push(create_student("エイミ", "Iemi", Rarity::Three));
|
||||
test.push(create_student("カリン", "Karin", Rarity::Three));
|
||||
test.push(create_student("ネル", "Neru", Rarity::Three));
|
||||
test.push(create_student("マキ", "Maki", Rarity::Three));
|
||||
test.push(create_student("ヒビキ", "Hibiki", Rarity::Three));
|
||||
test.push(create_student("サヤ", "Saya", Rarity::Three));
|
||||
test.push(create_student("シュン", "Shun", Rarity::Three));
|
||||
test.push(create_student("シロコ", "Shiroko", Rarity::Three));
|
||||
test.push(create_student("ホシノ", "Hoshino", Rarity::Three));
|
||||
test.push(create_student("ヒフミ", "Hifumi", Rarity::Three));
|
||||
test.push(create_student("ツルギ", "Tsurugi", Rarity::Three));
|
||||
|
||||
// Two Star
|
||||
test.push(create_student("アカリ", "Akari", Rarity::Two));
|
||||
test.push(create_student("ジュンコ", "Junko", Rarity::Two));
|
||||
test.push(create_student("ムツキ", "Mutsuki", Rarity::Two));
|
||||
test.push(create_student("カヨコ", "Kayoko", Rarity::Two));
|
||||
test.push(create_student("フウカ", "Fuuka", Rarity::Two));
|
||||
test.push(create_student("ユウカ", "Yuuka", Rarity::Two));
|
||||
test.push(create_student("アカネ", "Akane", Rarity::Two));
|
||||
test.push(create_student("ハル", "Haru", Rarity::Two));
|
||||
test.push(create_student("ウタハ", "Utaha", Rarity::Two));
|
||||
test.push(create_student("チセ", "Chise", Rarity::Two));
|
||||
test.push(create_student("ツバキ", "Tsubaki", Rarity::Two));
|
||||
test.push(create_student("セリカ", "Serika", Rarity::Two));
|
||||
test.push(create_student("アヤネ", "Ayane", Rarity::Two));
|
||||
test.push(create_student("ハスミ", "Hasumi", Rarity::Two));
|
||||
test.push(create_student("ハナエ", "Hanae", Rarity::Two));
|
||||
test.push(create_student("アイリ", "Airi", Rarity::Two));
|
||||
|
||||
// 1 Star:
|
||||
test.push(create_student("チナツ", "Chinatsu", Rarity::One));
|
||||
test.push(create_student("ハルカ", "Haruka", Rarity::One));
|
||||
test.push(create_student("ジュリ", "Juri", Rarity::One));
|
||||
test.push(create_student("コタマ", "Kotama", Rarity::One));
|
||||
test.push(create_student("アスナ", "Asuna", Rarity::One));
|
||||
test.push(create_student("コトリ", "Kotori", Rarity::One));
|
||||
test.push(create_student("フィーナ", "Pina", Rarity::One));
|
||||
test.push(create_student("スズミ", "Suzumi", Rarity::One));
|
||||
test.push(create_student("シミコ", "Shimiko", Rarity::One));
|
||||
test.push(create_student("セリナ", "Serina", Rarity::One));
|
||||
test.push(create_student("ヨシミ", "Yoshimi", Rarity::One));
|
||||
|
||||
test
|
||||
}
|
||||
|
||||
fn all_students() -> Vec<Student> {
|
||||
let mut students: Vec<Student> = Vec::with_capacity(45);
|
||||
|
||||
// 3 Star
|
||||
students.push(create_student("ヒナ", "Hina", Rarity::Three));
|
||||
students.push(create_student("イオリ", "Iori", Rarity::Three));
|
||||
students.push(create_student("ハルナ", "Haruna", Rarity::Three));
|
||||
students.push(create_student("イズミ", "Izumi", Rarity::Three));
|
||||
students.push(create_student("アル", "Aru", Rarity::Three));
|
||||
students.push(create_student("スミレ", "Sumire", Rarity::Three));
|
||||
students.push(create_student("エイミ", "Iemi", Rarity::Three));
|
||||
students.push(create_student("カリン", "Karin", Rarity::Three));
|
||||
students.push(create_student("ネル", "Neru", Rarity::Three));
|
||||
students.push(create_student("マキ", "Maki", Rarity::Three));
|
||||
students.push(create_student("ヒビキ", "Hibiki", Rarity::Three));
|
||||
students.push(create_student("サヤ", "Saya", Rarity::Three));
|
||||
students.push(create_student("シュン", "Shun", Rarity::Three));
|
||||
students.push(create_student("シロコ", "Shiroko", Rarity::Three));
|
||||
students.push(create_student("ホシノ", "Hoshino", Rarity::Three));
|
||||
students.push(create_student("ヒフミ", "Hifumi", Rarity::Three));
|
||||
students.push(create_student("ツルギ", "Tsurugi", Rarity::Three));
|
||||
|
||||
// Two Star
|
||||
students.push(create_student("アカリ", "Akari", Rarity::Two));
|
||||
students.push(create_student("ジュンコ", "Junko", Rarity::Two));
|
||||
students.push(create_student("ムツキ", "Mutsuki", Rarity::Two));
|
||||
students.push(create_student("カヨコ", "Kayoko", Rarity::Two));
|
||||
students.push(create_student("フウカ", "Fuuka", Rarity::Two));
|
||||
students.push(create_student("ユウカ", "Yuuka", Rarity::Two));
|
||||
students.push(create_student("アカネ", "Akane", Rarity::Two));
|
||||
students.push(create_student("ハル", "Haru", Rarity::Two));
|
||||
students.push(create_student("ウタハ", "Utaha", Rarity::Two));
|
||||
students.push(create_student("チセ", "Chise", Rarity::Two));
|
||||
students.push(create_student("ツバキ", "Tsubaki", Rarity::Two));
|
||||
students.push(create_student("セリカ", "Serika", Rarity::Two));
|
||||
students.push(create_student("アヤネ", "Ayane", Rarity::Two));
|
||||
students.push(create_student("ハスミ", "Hasumi", Rarity::Two));
|
||||
students.push(create_student("ハナエ", "Hanae", Rarity::Two));
|
||||
students.push(create_student("アイリ", "Airi", Rarity::Two));
|
||||
students.push(create_student("ノゾミ", "Nozomi", Rarity::Two)); // Not a part of Gacha
|
||||
|
||||
// 1 Star:
|
||||
students.push(create_student("チナツ", "Chinatsu", Rarity::One));
|
||||
students.push(create_student("ハルカ", "Haruka", Rarity::One));
|
||||
students.push(create_student("ジュリ", "Juri", Rarity::One));
|
||||
students.push(create_student("コタマ", "Kotama", Rarity::One));
|
||||
students.push(create_student("アスナ", "Asuna", Rarity::One));
|
||||
students.push(create_student("コトリ", "Kotori", Rarity::One));
|
||||
students.push(create_student("フィーナ", "Pina", Rarity::One));
|
||||
students.push(create_student("スズミ", "Suzumi", Rarity::One));
|
||||
students.push(create_student("シミコ", "Shimiko", Rarity::One));
|
||||
students.push(create_student("セリナ", "Serina", Rarity::One));
|
||||
students.push(create_student("ヨシミ", "Yoshimi", Rarity::One));
|
||||
|
||||
pub fn find_student(students: &[Student], jpn_name: &str) -> Option<Student> {
|
||||
students
|
||||
.iter()
|
||||
.find(|student| student.name == jpn_name)
|
||||
.map(|student| student.clone())
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use crate::gacha::Rarity;
|
||||
use crate::i18n::I18nString;
|
||||
use crate::i18n::Language;
|
||||
use crate::i18n::{I18nString, Language};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
||||
|
|
|
@ -0,0 +1,407 @@
|
|||
[
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"jpn": "ヒナ",
|
||||
"eng": "Hina"
|
||||
}
|
||||
},
|
||||
"rarity": 3
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"jpn": "イオリ",
|
||||
"eng": "Iori"
|
||||
}
|
||||
},
|
||||
"rarity": 3
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"jpn": "ハルナ",
|
||||
"eng": "Haruna"
|
||||
}
|
||||
},
|
||||
"rarity": 3
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"jpn": "イズミ",
|
||||
"eng": "Izumi"
|
||||
}
|
||||
},
|
||||
"rarity": 3
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"eng": "Aru",
|
||||
"jpn": "アル"
|
||||
}
|
||||
},
|
||||
"rarity": 3
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"jpn": "スミレ",
|
||||
"eng": "Sumire"
|
||||
}
|
||||
},
|
||||
"rarity": 3
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"jpn": "エイミ",
|
||||
"eng": "Iemi"
|
||||
}
|
||||
},
|
||||
"rarity": 3
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"eng": "Karin",
|
||||
"jpn": "カリン"
|
||||
}
|
||||
},
|
||||
"rarity": 3
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"jpn": "ネル",
|
||||
"eng": "Neru"
|
||||
}
|
||||
},
|
||||
"rarity": 3
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"eng": "Maki",
|
||||
"jpn": "マキ"
|
||||
}
|
||||
},
|
||||
"rarity": 3
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"eng": "Hibiki",
|
||||
"jpn": "ヒビキ"
|
||||
}
|
||||
},
|
||||
"rarity": 3
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"eng": "Saya",
|
||||
"jpn": "サヤ"
|
||||
}
|
||||
},
|
||||
"rarity": 3
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"eng": "Shun",
|
||||
"jpn": "シュン"
|
||||
}
|
||||
},
|
||||
"rarity": 3
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"eng": "Shiroko",
|
||||
"jpn": "シロコ"
|
||||
}
|
||||
},
|
||||
"rarity": 3
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"eng": "Hoshino",
|
||||
"jpn": "ホシノ"
|
||||
}
|
||||
},
|
||||
"rarity": 3
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"jpn": "ヒフミ",
|
||||
"eng": "Hifumi"
|
||||
}
|
||||
},
|
||||
"rarity": 3
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"eng": "Tsurugi",
|
||||
"jpn": "ツルギ"
|
||||
}
|
||||
},
|
||||
"rarity": 3
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"jpn": "アカリ",
|
||||
"eng": "Akari"
|
||||
}
|
||||
},
|
||||
"rarity": 2
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"jpn": "ジュンコ",
|
||||
"eng": "Junko"
|
||||
}
|
||||
},
|
||||
"rarity": 2
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"jpn": "ムツキ",
|
||||
"eng": "Mutsuki"
|
||||
}
|
||||
},
|
||||
"rarity": 2
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"eng": "Kayoko",
|
||||
"jpn": "カヨコ"
|
||||
}
|
||||
},
|
||||
"rarity": 2
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"jpn": "フウカ",
|
||||
"eng": "Fuuka"
|
||||
}
|
||||
},
|
||||
"rarity": 2
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"jpn": "ユウカ",
|
||||
"eng": "Yuuka"
|
||||
}
|
||||
},
|
||||
"rarity": 2
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"eng": "Akane",
|
||||
"jpn": "アカネ"
|
||||
}
|
||||
},
|
||||
"rarity": 2
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"jpn": "ハル",
|
||||
"eng": "Haru"
|
||||
}
|
||||
},
|
||||
"rarity": 2
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"eng": "Utaha",
|
||||
"jpn": "ウタハ"
|
||||
}
|
||||
},
|
||||
"rarity": 2
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"jpn": "チセ",
|
||||
"eng": "Chise"
|
||||
}
|
||||
},
|
||||
"rarity": 2
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"eng": "Tsubaki",
|
||||
"jpn": "ツバキ"
|
||||
}
|
||||
},
|
||||
"rarity": 2
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"jpn": "セリカ",
|
||||
"eng": "Serika"
|
||||
}
|
||||
},
|
||||
"rarity": 2
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"jpn": "アヤネ",
|
||||
"eng": "Ayane"
|
||||
}
|
||||
},
|
||||
"rarity": 2
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"eng": "Hasumi",
|
||||
"jpn": "ハスミ"
|
||||
}
|
||||
},
|
||||
"rarity": 2
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"eng": "Hanae",
|
||||
"jpn": "ハナエ"
|
||||
}
|
||||
},
|
||||
"rarity": 2
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"eng": "Airi",
|
||||
"jpn": "アイリ"
|
||||
}
|
||||
},
|
||||
"rarity": 2
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"jpn": "ノゾミ",
|
||||
"eng": "Nozomi"
|
||||
}
|
||||
},
|
||||
"rarity": 2
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"eng": "Chinatsu",
|
||||
"jpn": "チナツ"
|
||||
}
|
||||
},
|
||||
"rarity": 1
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"eng": "Haruka",
|
||||
"jpn": "ハルカ"
|
||||
}
|
||||
},
|
||||
"rarity": 1
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"jpn": "ジュリ",
|
||||
"eng": "Juri"
|
||||
}
|
||||
},
|
||||
"rarity": 1
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"jpn": "コタマ",
|
||||
"eng": "Kotama"
|
||||
}
|
||||
},
|
||||
"rarity": 1
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"jpn": "アスナ",
|
||||
"eng": "Asuna"
|
||||
}
|
||||
},
|
||||
"rarity": 1
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"jpn": "コトリ",
|
||||
"eng": "Kotori"
|
||||
}
|
||||
},
|
||||
"rarity": 1
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"jpn": "フィーナ",
|
||||
"eng": "Pina"
|
||||
}
|
||||
},
|
||||
"rarity": 1
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"jpn": "スズミ",
|
||||
"eng": "Suzumi"
|
||||
}
|
||||
},
|
||||
"rarity": 1
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"eng": "Shimiko",
|
||||
"jpn": "シミコ"
|
||||
}
|
||||
},
|
||||
"rarity": 1
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"eng": "Serina",
|
||||
"jpn": "セリナ"
|
||||
}
|
||||
},
|
||||
"rarity": 1
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"eng": "Yoshimi",
|
||||
"jpn": "ヨシミ"
|
||||
}
|
||||
},
|
||||
"rarity": 1
|
||||
}
|
||||
]
|
Loading…
Reference in New Issue