work
authorBen Pfaff <blp@cs.stanford.edu>
Wed, 24 Dec 2025 19:02:29 +0000 (11:02 -0800)
committerBen Pfaff <blp@cs.stanford.edu>
Wed, 24 Dec 2025 19:02:29 +0000 (11:02 -0800)
rust/pspp/src/format/decimals.rs
rust/pspp/src/spv/read/legacy_xml.rs
rust/pspp/src/spv/testdata/legacy5.expected

index 8813c00ff1060d2193c594a42830c351be91771a..12c7e80d9d35298c70c2e6cd9237448d8c23f86e 100644 (file)
@@ -9,8 +9,8 @@
 //! <https://cldr.unicode.org/index/downloads>, rename it as
 //! `cldr-json-full.zip` in the same directory as `build.rs`,
 //! and touch `build.rs` to force a rebuild.
-use crate::format::Decimal;
 use std::{collections::HashMap, sync::LazyLock};
+use crate::format::Decimal;
 
 /// Map from language to decimal point.
 pub static LANG_TO_DECIMAL: LazyLock<HashMap<&'static str, Decimal>> = LazyLock::new(|| {
index 5be84b3bca334230b57b349d0cab8d1bc58555f9..5998f8bb3f3dcf96bca24b1d1a42bfe3033bcc08 100644 (file)
@@ -297,7 +297,6 @@ impl Visualization {
                                 .into(),
                         );
                     }
-                    dbg!(entry);
                 }
             }
         }
@@ -311,7 +310,6 @@ impl Visualization {
                     .with_marker(footnote.marker.map(|s| Value::new_user_text(s))),
             );
         }
-        dbg!(&footnotes);
         let footnotes = pivot::Footnotes::from_iter(footnotes);
 
         for (purpose, area) in [
@@ -356,7 +354,7 @@ impl Visualization {
             }
         }
 
-        let mut series = HashMap::<&str, Series>::new();
+        let mut series = BTreeMap::<&str, Series>::new();
         while let n_source = source_variables.len()
             && let n_derived = derived_variables.len()
             && (n_source > 0 || n_derived > 0)
@@ -364,6 +362,7 @@ impl Visualization {
             for sv in take(&mut source_variables) {
                 match sv.decode(&data, &series) {
                     Ok(s) => {
+                        dbg!(&sv.id);
                         series.insert(&sv.id, s);
                     }
                     Err(()) => source_variables.push(sv),
@@ -373,6 +372,7 @@ impl Visualization {
             for dv in take(&mut derived_variables) {
                 match dv.decode(&series) {
                     Ok(s) => {
+                        eprintln!("{:?} {:?} {:?}", &dv.id, dv.depends_on, &dv.value);
                         series.insert(&dv.id, s);
                     }
                     Err(()) => derived_variables.push(dv),
@@ -480,16 +480,11 @@ impl Visualization {
                 let mut coordinate_to_index = HashMap::new();
                 let mut next_cats = Vec::with_capacity(cats.len());
                 let mut start = 0;
-                dbg!(&variable.name, &variable.values);
                 for end in 1..=cats.len() {
                     let dv1 = &variable.values[cats[start].index];
-                    if end < cats.len() && &variable.values[cats[end].index].value == &dv1.value {
-                        println!("categories {start}..={end} have same value {dv1:?}");
-                    } else {
-                        dbg!(start..end);
+                    if end >= cats.len() || &variable.values[cats[end].index].value != &dv1.value {
                         let name = variable.map.lookup(dv1);
                         if name.is_number_or(|s| !s.is_empty()) {
-                            dbg!();
                             let name = variable.new_name(dv1, footnotes);
                             let mut group = Group::new(name);
                             for i in start..end {
@@ -506,7 +501,6 @@ impl Visualization {
                             next_cats.push(next_cat);
                         } else {
                             // XXX coordinate_to_index?
-                            dbg!();
                             for cat in &cats[start..end] {
                                 next_cats.push(cat.clone());
                             }
@@ -516,7 +510,6 @@ impl Visualization {
                 }
                 *variable.coordinate_to_index.borrow_mut() = coordinate_to_index;
                 cats = next_cats;
-                dbg!(&cats);
             }
 
             let dimension = Dimension::new(
@@ -542,7 +535,7 @@ impl Visualization {
 
         fn decode_dimensions<'a, 'b>(
             variables: impl IntoIterator<Item = &'a str>,
-            series: &'b HashMap<&str, Series>,
+            series: &'b BTreeMap<&str, Series>,
             axes: &HashMap<usize, &Axis>,
             styles: &HashMap<&str, &Style>,
             a: Axis3,
@@ -722,13 +715,11 @@ impl Visualization {
                 // XXX indexing
                 let dv = &cell_footnotes.values[i];
                 if let Some(s) = dv.value.as_string() {
-                    dbg!(dv);
                     for part in s.split(',') {
                         if let Ok(index) = part.parse::<usize>()
                             && let Some(index) = index.checked_sub(1)
                             && let Some(footnote) = footnotes.get(index)
                         {
-                            dbg!(footnote);
                             value = value.with_footnote(footnote);
                         }
                     }
@@ -798,7 +789,7 @@ impl Visualization {
                     &self,
                     intersect: &Intersect,
                     look: &mut Look,
-                    series: &HashMap<&str, Series>,
+                    series: &BTreeMap<&str, Series>,
                     dims: &mut [Dim],
                     data: &mut HashMap<Vec<usize>, Value>,
                 ) {
@@ -1033,7 +1024,7 @@ impl Visualization {
             .with_footnotes(footnotes)
             .with_data(data)
             .with_layer(&current_layer);
-        let decimal = dbg!(Decimal::for_lang(dbg!(&self.lang)));
+        let decimal = Decimal::for_lang(&self.lang);
         if pivot_table.style.settings.decimal != decimal {
             Arc::make_mut(&mut pivot_table.style.settings).decimal = decimal;
         }
@@ -1157,7 +1148,7 @@ impl SourceVariable {
     fn decode(
         &self,
         data: &IndexMap<String, IndexMap<String, Vec<DataValue>>>,
-        series: &HashMap<&str, Series>,
+        series: &BTreeMap<&str, Series>,
     ) -> Result<Series, ()> {
         let label_series = if let Some(label_variable) = &self.label_variable {
             let Some(label_series) = series.get(label_variable.references.as_str()) else {
@@ -1204,16 +1195,29 @@ struct DerivedVariable {
     string_format: Option<StringFormat>,
     #[serde(default, rename = "valueMapEntry")]
     value_map: Vec<ValueMapEntry>,
+    #[serde(rename = "@dependsOn")]
+    depends_on: Option<String>,
 }
 
 impl DerivedVariable {
-    fn decode(&self, series: &HashMap<&str, Series>) -> Result<Series, ()> {
-        let mut values = if self.value == "constant(0)" {
-            let n_values = if let Some(series) = series.values().next() {
-                series.values.len()
-            } else {
-                return Err(());
-            };
+    fn decode(&self, series: &BTreeMap<&str, Series>) -> Result<Series, ()> {
+        let mut values = if self.id == "column" || self.id == "row" {
+            vec![]
+        } else if let Some(rest) = self.id.strip_prefix("dimension")
+            && rest.parse::<usize>().is_ok()
+        {
+            vec![]
+        } else if self.value == "constant(0)" {
+            let n_values = series
+                .values()
+                .find_map(|series| {
+                    if !series.values.is_empty() {
+                        Some(series.values.len())
+                    } else {
+                        None
+                    }
+                })
+                .ok_or(())?;
             (0..n_values)
                 .map(|_| DataValue {
                     index: Some(0.0),
@@ -2429,7 +2433,7 @@ struct Labeling {
 impl Labeling {
     fn decode_format_map<'a>(
         &self,
-        series: &'a HashMap<&str, Series>,
+        series: &'a BTreeMap<&str, Series>,
     ) -> (Option<&'a Series>, HashMap<i64, crate::format::Format>) {
         let mut map = HashMap::new();
         let mut cell_format = None;
index c130b3cc6749e5c391aa677990c562a259b8689a..e4ed57eeb1046a122b2e5041cc15d2c55829dcf9 100644 (file)
@@ -1,6 +1,6 @@
-  Statistics
+   Statistics
 Variables: Finished
-╭───────┬───╮
-│Valid  │159│
-│Missing│  0│
-╰───────┴───╯
\95­â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94¬â\94\80â\94\80â\94\80â\95®
+│Valid  │159│
+│  Missing│  0│
\95°â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94\80â\94´â\94\80â\94\80â\94\80â\95¯