1#![cfg_attr(coverage_nightly, feature(coverage_attribute))]
2#![cfg_attr(test, allow(clippy::needless_pass_by_value))]
3#![cfg_attr(test, allow(clippy::missing_panics_doc))]
4#![allow(clippy::wildcard_imports)]
5#![allow(unused_imports)]
6
7use std::{
8 any::Any,
9 borrow::Borrow,
10 cmp, convert, fmt, io, mem,
11 num::{ParseFloatError, ParseIntError},
12 ops, ptr,
13 rc::Rc,
14 str::FromStr,
15 thread,
16};
17
18use bitflags::bitflags;
19use openpql_macro::*;
20pub use openpql_pql_parser::parse_pql;
21use openpql_pql_parser::{Error as SyntaxError, Spanned, *};
22use openpql_prelude::{CardGen, HandN, ParseError, PlayerIdx};
23use openpql_range_parser::{BoardRangeChecker, Error as RangeError, RangeChecker};
24use runner_output::*;
25
26mod error;
27mod functions;
28mod helper_loc;
29mod output_aggregator;
30mod runner;
31mod runner_output;
32mod types;
33mod vm;
34
35pub use error::*;
36use functions::*;
37use helper_loc::*;
38use output_aggregator::*;
39pub use runner::*;
40#[cfg(test)]
41pub use tests::*;
42pub use types::*;
43use vm::{Vm, VmBinOpCmp, VmCache, VmExecContext, VmProgram, VmSampledData, VmStackValue};
44
45type HeapIdx = usize;
46type FractionInner = i32;
47type RangeSrc = String;
48type FnCheckRange = Box<dyn Fn(&[PQLCard]) -> bool + Send + Sync>;
49
50fn parse_cards(text: &str) -> Option<PQLCardSet> {
51 let mut res = PQLCardSet::default();
52 let mut iter = text.chars().filter(|c| !c.is_whitespace());
53
54 while let Some(rank) = iter.next() {
55 let suit = iter.next()?;
56
57 dbg!(suit);
58 res.set(PQLCard::new(
59 PQLRank::from_char(rank)?,
60 PQLSuit::from_char(suit)?,
61 ));
62 }
63
64 Some(res)
65}
66
67#[cfg(test)]
68pub mod tests {
69 pub use std::fmt::Write;
70
71 pub use itertools::Itertools;
72 use openpql_pql_parser::*;
73 pub use openpql_prelude::{CardN, c64, card, cards, r16};
74 pub use quickcheck::{Arbitrary, TestResult};
75 pub use quickcheck_macros::quickcheck;
76 pub use rand::{SeedableRng, prelude::*, rngs};
77
78 pub use super::{
79 PQLBoardRange, PQLGame, PQLHiRating, PQLRange,
80 functions::{PQLFnContext, TestPQLFnContext, rate_hi_hand},
81 };
82 use super::{PQLCard, PQLCardCount, PQLError, PQLErrorKind, PQLRank};
83
84 pub fn count_suits(cs: &[PQLCard]) -> PQLCardCount {
85 cs.iter().map(|c| c.suit).unique().count().to_le_bytes()[0]
86 }
87
88 pub fn get_ranks(cs: &[PQLCard]) -> Vec<PQLRank> {
89 cs.iter().map(|c| c.rank).collect()
90 }
91
92 pub fn mk_ranges(
93 game: PQLGame,
94 player: &[&str],
95 board: &str,
96 ) -> (Vec<PQLRange>, PQLBoardRange) {
97 let player_ranges = player
98 .iter()
99 .map(|&s| (game, s).try_into().unwrap())
100 .collect();
101
102 let board_range = (game, board).try_into().unwrap();
103
104 (player_ranges, board_range)
105 }
106
107 pub fn mk_rating(text: &str) -> PQLHiRating {
108 rate_hi_hand(&PQLFnContext::default(), &text.to_string()).unwrap()
109 }
110}