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, PerPlayer, 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)]
68#[cfg_attr(coverage_nightly, coverage(off))]
69pub mod tests {
70 pub use std::fmt::Write;
71
72 pub use itertools::Itertools;
73 use openpql_pql_parser::*;
74 pub use openpql_prelude::{CardN, c64, card, cards, r16};
75 pub use quickcheck::{Arbitrary, TestResult};
76 pub use quickcheck_macros::quickcheck;
77 pub use rand::{SeedableRng, prelude::*, rngs};
78
79 pub use super::{
80 PQLBoardRange, PQLGame, PQLHiRating, PQLRange,
81 functions::{PQLFnContext, TestPQLFnContext, rate_hi_hand},
82 };
83 use super::{PQLCard, PQLCardCount, PQLError, PQLErrorKind, PQLRank};
84
85 pub fn count_suits(cs: &[PQLCard]) -> PQLCardCount {
86 cs.iter().map(|c| c.suit).unique().count().to_le_bytes()[0]
87 }
88
89 pub fn get_ranks(cs: &[PQLCard]) -> Vec<PQLRank> {
90 cs.iter().map(|c| c.rank).collect()
91 }
92
93 pub fn mk_ranges(
94 game: PQLGame,
95 player: &[&str],
96 board: &str,
97 ) -> (Vec<PQLRange>, PQLBoardRange) {
98 let player_ranges = player
99 .iter()
100 .map(|&s| (game, s).try_into().unwrap())
101 .collect();
102
103 let board_range = (game, board).try_into().unwrap();
104
105 (player_ranges, board_range)
106 }
107
108 pub fn mk_rating(text: &str) -> PQLHiRating {
109 rate_hi_hand(&PQLFnContext::default(), &text.to_string()).unwrap()
110 }
111}