screenplay_doc_parser_rs/
pdf_parser.rs1use core::num;
5use core::time;
6use std::collections::HashMap;
7use std::collections::HashSet;
8use std::hash::Hash;
9use std::ops::Not;
10use std::process::id;
11use std::sync::RwLockReadGuard;
12use std::thread::panicking;
13
14use uuid::Uuid;
15
16use crate::pdf_document;
17use crate::pdf_document::ElementIndentationsInches;
18use crate::pdf_document::ElementIndentationsPoints;
19use crate::screenplay_document::Character;
20use crate::screenplay_document::Environment;
21use crate::screenplay_document::EnvironmentStrings;
22use crate::screenplay_document::LocationID;
23use crate::screenplay_document::LocationNode;
24use crate::screenplay_document::PageNumber;
25use crate::screenplay_document::SPType;
26
27use crate::screenplay_document;
28use crate::screenplay_document::Scene;
29use crate::screenplay_document::SceneHeadingElement;
30use crate::screenplay_document::SceneID;
31use crate::screenplay_document::SceneNumber;
32use crate::screenplay_document::ScreenplayCoordinate;
33use crate::screenplay_document::TextElement;
34
35pub mod indentations_deducer;
36
37pub fn deduce_indentations(
38 pdfdoc: &pdf_document::PDFDocument,
39) -> Option<ElementIndentationsInches> {
40 unimplemented!();
41 let mut x_pos_vec: Vec<f64> = Vec::default();
42
43 let mut lines_count = 0;
44 for page in &pdfdoc.pages {
45 for ln in &page.lines {
46 if let Some(word) = ln.words.first() {
47 x_pos_vec.push(word.position.x);
48 lines_count += 1;
49 }
50 }
51 }
52
53 let mut x_freq_map: HashMap<i32, i32> = HashMap::new();
54
55 for entry in x_pos_vec {
56 let rounded = entry.round() as i32;
57 let new_ent = x_freq_map.entry(rounded).or_insert(0);
58 *new_ent += 1;
59 }
60
61 let mut x_freq_keys: Vec<i32> = x_freq_map.keys().cloned().collect();
62 x_freq_keys.sort();
63
64 for fk in &x_freq_keys {
65 let v = x_freq_map.get(&fk);
66 println!(
67 "INDENT_INCHES: {:10.2} FREQUENCY: {:6.2}%",
68 fk.clone() as f64 / 72.0,
69 {
70 if let Some(freq) = v {
71 let fr = *freq;
72 (fr as f64 / lines_count as f64) * 100.0
73 } else {
74 0.0
75 }
76 }
77 )
78 }
79
80 None
81}
82
83fn _is_word_within_content_zone(
84 pdf_word: &pdf_document::Word,
85 element_indentaions_pts: &ElementIndentationsPoints,
86) -> bool {
87 todo!()
88}
89
90fn _check_non_content_type(
91 pdf_word: &pdf_document::Word,
92 new_line: &screenplay_document::Line,
93 element_indentaions_pts: &ElementIndentationsPoints,
94 time_of_day_strs: &screenplay_document::TimeOfDayCollection,
95 environment_strs: &screenplay_document::EnvironmentStrings,
96 r_marker: &String,
97) -> Option<SPType> {
98 todo!()
99}
100
101fn _get_type_for_word(
102 pdf_word: &pdf_document::Word,
103 new_line: &screenplay_document::Line,
104 element_indentaions_pts: &ElementIndentationsPoints,
105 time_of_day_strs: &screenplay_document::TimeOfDayCollection,
106 environment_strs: &screenplay_document::EnvironmentStrings,
107 r_marker: &String,
108) -> Option<SPType> {
109 use screenplay_document::SPType::*;
110 use screenplay_document::SceneHeadingElement;
111
112 let previous_element_type = match new_line.text_elements.last() {
113 None => SPType::NONE,
114 Some(e) => match &e.element_type {
115 None => SPType::NONE,
116 Some(t) => t.clone(),
117 },
118 };
119
120 let char_width = pdf_word.font_size * 0.6; let position_tolerance: f64 = 0.01;
123
124 if (new_line.line_type == Some(SPType::SP_SCENE_HEADING(SceneHeadingElement::Line)))
126 && (pdf_word.position.x >= element_indentaions_pts.right)
127 {
128 if pdf_word.text == *r_marker {
129 return Some(SPType::SP_LINE_REVISION_MARKER);
130 }
131 return Some(SPType::SP_SCENENUM);
132 }
133
134 match previous_element_type {
136 SPType::SP_SCENE_HEADING(SceneHeadingElement::TimeOfDay) => {
138 if pdf_word.text == "-".to_string() {
139 return Some(SPType::SP_SCENE_HEADING(SceneHeadingElement::Separator));
140 }
141 return None;
142 }
143 SPType::SP_SCENE_HEADING(SceneHeadingElement::Separator) => {
144 let type_before_separator =
145 match new_line.text_elements.get(new_line.text_elements.len() - 2) {
146 None => SPType::NONE,
147 Some(t) => match &t.element_type {
148 None => SPType::NONE,
149 Some(e) => e.clone(),
150 },
151 };
152
153 if time_of_day_strs.is_time_of_day(&pdf_word.text) {
154 return Some(SP_SCENE_HEADING(SceneHeadingElement::TimeOfDay));
155 }
156
157 match type_before_separator {
158 SPType::NONE => return None, SPType::SP_SCENE_HEADING(SceneHeadingElement::Location) => {
160 return Some(SP_SCENE_HEADING(SceneHeadingElement::SubLocation));
161 }
162 SPType::SP_SCENE_HEADING(SceneHeadingElement::Location) => {
163 if pdf_word.text == "-".to_string() {
164 return Some(SP_SCENE_HEADING(SceneHeadingElement::Separator));
165 }
166 return Some(SP_SCENE_HEADING(SceneHeadingElement::SubLocation));
167 }
168 SPType::SP_SCENE_HEADING(SceneHeadingElement::TimeOfDay)
169 | SP_SCENE_HEADING(SceneHeadingElement::SlugOther) => {
170 return Some(SP_SCENE_HEADING(SceneHeadingElement::SlugOther));
171 }
172 _ => {
173 dbg!(&pdf_word.text);
174 dbg!(type_before_separator);
175 return Some(SP_SCENE_HEADING(SceneHeadingElement::SlugOther));
177 }
178 }
179 }
180 SPType::SP_PARENTHETICAL => return Some(previous_element_type.clone()),
181 SPType::SP_SCENE_HEADING(SceneHeadingElement::SubLocation) => {
182 if pdf_word.text == "-".to_string() {
183 return Some(SP_SCENE_HEADING(SceneHeadingElement::Separator));
184 }
185 return Some(SP_SCENE_HEADING(SceneHeadingElement::SubLocation));
186 }
187 SPType::SP_SCENE_HEADING(SceneHeadingElement::Location) => {
188 if pdf_word.text == "-".to_string() {
189 return Some(SP_SCENE_HEADING(SceneHeadingElement::Separator));
190 }
191 return Some(SP_SCENE_HEADING(SceneHeadingElement::Location));
192 }
193 SPType::SP_SCENE_HEADING(SceneHeadingElement::Environment) => {
194 return Some(SP_SCENE_HEADING(SceneHeadingElement::Location));
195 }
196 SPType::SP_CHARACTER => {
197 if pdf_word.text.starts_with("(") {
204 return Some(SPType::SP_CHARACTER_EXTENSION);
205 } else {
206 if pdf_word.text == *r_marker {
207 return Some(SPType::SP_LINE_REVISION_MARKER);
208 }
209 return Some(SPType::SP_CHARACTER);
210 }
211 }
212 SPType::SP_DD_L_CHARACTER => {
213 if pdf_word.text.starts_with("(") {
214 return Some(SPType::SP_DD_L_CHARACTER_EXTENSION);
215 } else {
216 return Some(SPType::SP_DD_L_CHARACTER);
217 }
218 }
219 SPType::SP_DD_R_CHARACTER => {
220 if pdf_word.text.starts_with("(") {
221 return Some(SPType::SP_DD_R_CHARACTER_EXTENSION);
222 } else {
223 return Some(SPType::SP_DD_R_CHARACTER);
224 }
225 }
226 SPType::SP_DD_L_CHARACTER_EXTENSION
227 | SPType::SP_DD_R_CHARACTER_EXTENSION
228 | SPType::SP_CHARACTER_EXTENSION => {
229 return Some(previous_element_type.clone());
230 }
231
232 _ => {
233 if pdf_word.position.y < element_indentaions_pts.top
239 && pdf_word.position.y > element_indentaions_pts.bottom
240 {
241 if pdf_word.position.x < element_indentaions_pts.left {
245 return Some(SPType::SP_SCENENUM);
246 }
247 else if pdf_word.position.x >= element_indentaions_pts.right {
250 if pdf_word.text == *r_marker {
251 return Some(SPType::SP_LINE_REVISION_MARKER);
252 }
253 return Some(SPType::SP_SCENENUM);
254 } else {
255 let _within_tolerance = |target| {
256 if (&pdf_word.position.x - &target).abs() > position_tolerance {
257 return false;
258 } else {
259 return true;
260 };
261 };
262
263 if _within_tolerance(element_indentaions_pts.action) {
267 if let Some(_) = Environment::from_str(&pdf_word.text, environment_strs) {
270 return Some(SP_SCENE_HEADING(SceneHeadingElement::Environment));
271 } else if new_line.line_type == None {
272 return Some(SPType::SP_ACTION);
273 };
274 }
275 if _within_tolerance(element_indentaions_pts.character)
276 && new_line.line_type == None
277 {
278 return Some(SPType::SP_CHARACTER);
279 } else if _within_tolerance(element_indentaions_pts.dialogue)
280 && new_line.line_type == None
281 {
282 return Some(SPType::SP_DIALOGUE);
283 } else if _within_tolerance(element_indentaions_pts.parenthetical)
284 && pdf_word.text.starts_with("(")
285 && new_line.line_type == None
286 {
287 return Some(SPType::SP_PARENTHETICAL);
288 } else {
289 return None;
290 }
291 };
292 }
293
294 if pdf_word.position.y >= element_indentaions_pts.top {
297 let wordwidth: f64 = char_width * f64::from(pdf_word.text.len() as i32);
298 let rightedge: f64 = wordwidth + pdf_word.position.x;
299 if pdf_word.position.x < element_indentaions_pts.pagewidth / 3.0 {
300 return Some(SPType::NON_CONTENT_TOP);
301 } else if (element_indentaions_pts.pagewidth - pdf_word.position.x)
302 < (element_indentaions_pts.pagewidth / 4.0)
303 && (pdf_word.text.ends_with("."))
304 {
305 return Some(SPType::SP_PAGENUM);
306 } else {
307 return Some(SPType::NON_CONTENT_TOP);
308 }
309 }
310 if pdf_word.text.contains("(MORE)")
312 | pdf_word.text.contains("(CONTINUED)")
313 | pdf_word.text.contains("(CONT'D)")
314 {
315 return Some(SPType::SP_MORE_CONTINUED);
316 } else {
317 return Some(SPType::NON_CONTENT_BOTTOM);
318 }
319 }
320 }
321}
322
323pub fn get_screenplay_doc_from_pdf_obj(
324 doc: pdf_document::PDFDocument,
325 element_indent_in_opt: Option<ElementIndentationsInches>,
326 rev_marker_opt: Option<String>,
327 time_of_day_strs_opt: Option<screenplay_document::TimeOfDayCollection>,
328 env_strs_opt: Option<EnvironmentStrings>,
329) -> Option<screenplay_document::ScreenplayDocument> {
330 use screenplay_document::ScreenplayDocument;
331
332 if doc.pages.len() < 1 {
333 return None;
334 }
335
336 let time_of_day_strs: screenplay_document::TimeOfDayCollection;
337 if let Some(tds) = time_of_day_strs_opt {
338 time_of_day_strs = tds;
339 } else {
340 time_of_day_strs = screenplay_document::TimeOfDayCollection::default();
341 }
342
343 let environment_strs: screenplay_document::EnvironmentStrings;
344 if let Some(evs) = env_strs_opt {
345 environment_strs = evs;
346 } else {
347 environment_strs = EnvironmentStrings::default();
348 }
349
350 let r_marker;
351 if let Some(rm) = rev_marker_opt {
352 r_marker = rm;
353 } else {
354 r_marker = "*".to_string();
355 }
356
357 let mut new_screenplay_doc: ScreenplayDocument = ScreenplayDocument::default();
358
359 for pdf_page in doc.pages.iter() {
360 if pdf_page.lines.len() < 1 {
361 continue;
362 };
363 let mut new_page = screenplay_document::Page::default();
366
367 let mut prev_line_y_pos: f64 = 0.0;
368 let mut line_height: f64 = 12.0; let mut current_resolution: f64 = 72.0;
379 let element_indentaions_pts;
380 if let Some(ref indentations) = element_indent_in_opt {
381 element_indentaions_pts =
382 ElementIndentationsPoints::from_inches(indentations, &Some(current_resolution));
383 } else {
384 element_indentaions_pts =
385 ElementIndentationsPoints::us_letter_default(&Some(current_resolution));
386 }
387 for (pdf_l_idx, pdf_line) in pdf_page.lines.iter().enumerate() {
388 if pdf_line.words.len() < 1 {
389 continue;
390 };
391
392 let mut new_line = screenplay_document::Line::default();
393 let mut previous_element_type: SPType = SPType::NONE;
394 let mut word_counter: usize = 0;
395 for pdf_word in pdf_line.words.iter() {
396 let mut new_text_element = screenplay_document::TextElement::default();
398
399 let new_word_type: Option<SPType> = _get_type_for_word(
400 &pdf_word,
401 &new_line,
402 &element_indentaions_pts,
403 &time_of_day_strs,
404 &environment_strs,
405 &r_marker,
406 );
407
408 new_text_element.element_position = Some(pdf_word.position.clone());
410
411 if let Some(nwt) = new_word_type {
412 match nwt {
413 SPType::SP_DIALOGUE => {
415 if new_line.line_type == None {
416 new_line.line_type = Some(SPType::SP_DIALOGUE);
417 }
418 }
419 SPType::SP_PARENTHETICAL => {
420 if new_line.line_type == None {
421 new_line.line_type = Some(SPType::SP_PARENTHETICAL);
422 }
423 }
424 SPType::SP_DD_L_PARENTHETICAL
425 | SPType::SP_DD_R_PARENTHETICAL
426 | SPType::SP_DD_L_DIALOGUE
427 | SPType::SP_DD_R_DIALOGUE => {
428 new_line.line_type = Some(SPType::SP_DUAL_DIALOGUES);
429 }
430 SPType::SP_CHARACTER => {
431 if new_line.line_type == None {
432 new_line.line_type = Some(SPType::SP_CHARACTER);
433 }
434 }
435 SPType::SP_DD_L_CHARACTER | SPType::SP_DD_R_CHARACTER => {
436 if new_line.line_type == None {
437 new_line.line_type = Some(SPType::SP_DUAL_CHARACTERS);
438 }
439 }
440 SPType::SP_ACTION => {
441 if new_line.line_type == None {
442 new_line.line_type = Some(SPType::SP_ACTION);
443 }
444 }
445 SPType::SP_SCENE_HEADING(SceneHeadingElement::Environment) => {
446 use screenplay_document::SceneHeadingElement;
447 if new_line.line_type == None {
448 new_line.line_type =
449 Some(SPType::SP_SCENE_HEADING(SceneHeadingElement::Line));
450 }
451 }
452
453 SPType::SP_PAGENUM => {
458 if new_line.line_type == None {
459 new_line.line_type = Some(SPType::SP_PAGE_HEADER);
460 }
461 new_page.page_number = Some(PageNumber(pdf_word.text.clone()));
462 }
464 SPType::SP_PAGE_REVISION_LABEL => {
465 new_page.revised = true;
468 }
470 SPType::NON_CONTENT_TOP
471 | SPType::NON_CONTENT_BOTTOM
472 | SPType::NON_CONTENT_LEFT
473 | SPType::NON_CONTENT_RIGHT => {
474 }
479 SPType::SP_SCENENUM => {
480 if pdf_word.text.contains(&r_marker) {
483 new_line.revised = true;
484 }
485 let maybe_scene_num = Some(
486 pdf_word
487 .text
488 .trim_matches('*') .to_string()
490 .trim_matches('.')
491 .to_string(),
492 );
493 if let Some(sn) = maybe_scene_num {
494 if !sn.is_empty() {
495 new_line.scene_number = Some(sn);
496 use screenplay_document::SceneHeadingElement;
497 match new_line.line_type {
498 Some(SPType::NONE) => {
499 new_line.line_type = Some(SPType::SP_SCENE_HEADING(
500 SceneHeadingElement::Line,
501 ));
502 }
503 _ => {}
504 }
505 previous_element_type = SPType::SP_SCENENUM;
506 }
507 }
508
509 }
511 SPType::SP_LINE_REVISION_MARKER => {
512 new_line.revised = true;
513 previous_element_type = SPType::SP_LINE_REVISION_MARKER;
514 }
516
517 _ => {}
518 }
519 }
520
521 new_text_element.element_type = new_word_type.clone();
522 new_text_element.text = pdf_word.text.clone();
523
524 if word_counter > 0 {
529 if let Some(last_word) = pdf_line.words.last() {
530 let char_width: f64 = 7.2;
531 let whitespace_chars: u64 = u64::from(
532 ((pdf_word.position.x - (last_word.position.x + last_word.bbox_width))
533 / char_width)
534 .round() as u64,
535 );
536
537 if whitespace_chars >= 1 {
538 match previous_element_type {
539 SPType::SP_SCENENUM | SPType::SP_LINE_REVISION_MARKER => {
540 new_text_element.preceding_whitespace_chars = 0;
541 }
542 _ => {
543 new_text_element.preceding_whitespace_chars = whitespace_chars;
544 }
545 }
546 } else {
547 new_text_element.preceding_whitespace_chars = 1
550 }
551 };
552 }
553 if let Some(new_type) = new_word_type.clone() {
554 previous_element_type = new_type;
555 } else {
556 previous_element_type = SPType::NONE;
557 }
558
559 new_line.text_elements.push(new_text_element);
560 word_counter += 1;
563 }
564 let cur_y_pos = pdf_line.words.first().unwrap().position.y;
566 if prev_line_y_pos > 1.0 {
567 let y_delta = prev_line_y_pos - cur_y_pos;
568 if y_delta > line_height { let blank_lines_count: u64 = (y_delta / line_height).round() as u64 - 1;
570 new_line.preceding_empty_lines = blank_lines_count;
571 }
572 }
573
574 prev_line_y_pos = cur_y_pos;
575 if new_line.text_elements.is_empty() {
576 continue;
577 }
578
579 match new_line.line_type {
580 None => {}
581 Some(SPType::SP_CHARACTER) => {
583 let mut character_name = String::new();
584 for element in &new_line.text_elements {
585 if element.element_type == Some(SPType::SP_CHARACTER) {
586 if !character_name.is_empty() {
587 character_name.push(' ');
588 }
589 character_name.push_str(&element.text);
590 }
591 }
592 let mut character_exists_in_doc = false;
595 if !&new_screenplay_doc.characters.is_empty() {
596 for character in &new_screenplay_doc.characters {
597 if character.name == character_name {
598 character_exists_in_doc = true;
599 }
600 }
601 }
602 if !character_exists_in_doc{
603
604 let new_character = Character {
605 name: character_name,
606 id: screenplay_document::CharacterID::new(),
607 };
608 new_screenplay_doc.characters.insert(new_character);
609 }
610 }
611 Some(SPType::SP_SCENE_HEADING(SceneHeadingElement::Line)) => {
613 let maybe_first_word = &new_line
615 .text_elements
616 .iter()
617 .filter(|te| {
618 te.element_type
619 == Some(SPType::SP_SCENE_HEADING(SceneHeadingElement::Environment))
620 })
621 .take(1)
622 .next();
623
624 let mut new_line_env = Environment::Ext;
625
626 if let Some(fw) = maybe_first_word {
627 new_line_env = Environment::from_str(&fw.text, &environment_strs).unwrap();
628 }
629
630 let mut root_location_string: String = String::new();
633
634 let mut current_sub_location_string = String::new();
635 let mut full_path: Vec<String> = Vec::new();
636 let mut root_location_done = false;
637
638 for element in &new_line.text_elements {
639 match element.element_type {
640 Some(SPType::SP_SCENE_HEADING(SceneHeadingElement::Location))
641 | Some(SPType::SP_SCENE_HEADING(SceneHeadingElement::Environment)) => {
642 if !root_location_string.is_empty() {
643 root_location_string.push(' ');
644 }
645 root_location_string.push_str(&element.text.clone());
646 }
647 Some(SPType::SP_SCENE_HEADING(SceneHeadingElement::Separator)) => {
648 if root_location_done {
649 if !current_sub_location_string.is_empty() {
650 full_path.push(current_sub_location_string.clone());
651 current_sub_location_string = String::new();
652 }
653 } else {
654 root_location_done = true;
655 full_path.push(root_location_string.clone());
656 }
657 }
658 Some(SPType::SP_SCENE_HEADING(SceneHeadingElement::SubLocation)) => {
659 if !current_sub_location_string.is_empty() {
660 current_sub_location_string.push(' ');
661 }
662 current_sub_location_string.push_str(&element.text.clone());
663 }
664 _ => {
665 if !root_location_string.is_empty() {
666 break;
667 }
668 }
669 }
670 }
671
672 let mut location_id_to_insert: Option<LocationID> = None;
673 let mut exists: bool = false;
674
675 for (existing_id, existing_root) in &new_screenplay_doc.locations {
676 if existing_root.superlocation.is_some() {
677 continue;
678 }
679 if root_location_string == existing_root.string {
680 location_id_to_insert = Some(existing_id.clone());
681 exists = true;
682 }
683 }
684
685 if !exists {
686 location_id_to_insert = Some(LocationID::new());
687
688 let new_root_location: LocationNode = LocationNode {
689 string: root_location_string.clone(),
690 sublocations: HashSet::new(),
691 superlocation: None,
692 };
693 new_screenplay_doc
694 .locations
695 .insert(location_id_to_insert.clone().unwrap(), new_root_location);
696 }
697
698 if let Some((id, s_path)) =
701 crate::reports::location_path_exists(&new_screenplay_doc, &full_path)
702
703 {
704 let mut current_id = id.clone();
705
706 for pathstring in s_path {
707 if let Some(location) =
708 &mut new_screenplay_doc.locations.get_mut(¤t_id)
709 {
710 let new_id = LocationID::new();
711
712 let new_location = LocationNode {
713 string: pathstring.clone(),
714 sublocations: HashSet::new(),
715 superlocation: Some(current_id.clone()),
716 };
717 current_id = new_id.clone();
718 location_id_to_insert = Some(new_id.clone());
719 location.add_sublocation(new_id.clone());
720 new_screenplay_doc
721 .locations
722 .insert(new_id.clone(), new_location);
723 }
724 }
725 }
726
727 let new_scene = Scene {
729 number: {
730 if let Some(num) = &new_line.scene_number.clone() {
731 Some(SceneNumber(num.clone()))
732 } else {
733 None
734 }
735 },
736 environment: new_line_env,
737 start: ScreenplayCoordinate {
738 page: new_screenplay_doc.pages.len(),
739 line: new_page.lines.len(),
740 element: None,
741 },
742 revised: new_line.revised,
743 story_locations: {
744 if let Some(id) = location_id_to_insert {
745 vec![id.clone()]
746 } else {
747 Vec::new()
748 }
749 },
750 story_time_of_day: {
751 let maybe_time: Vec<TextElement> = new_line
752 .text_elements
753 .iter()
754 .filter(|el| {
755 el.element_type
756 == Some(SPType::SP_SCENE_HEADING(
757 SceneHeadingElement::TimeOfDay,
758 ))
759 })
760 .map(|el| el.clone())
761 .collect();
762 match maybe_time.is_empty() {
763 true => None,
764 false => time_of_day_strs
765 .get_time_of_day(&maybe_time.first().unwrap().text),
766 }
767 },
768 };
769 let new_scene_id = SceneID::new();
770 new_line.scene_id = Some(new_scene_id.clone());
771 new_screenplay_doc.scenes.insert(new_scene_id, new_scene);
772 }
773 _ => {}
774 }
775
776 if let Some(SPType::SP_SCENE_HEADING(SceneHeadingElement::Line)) = new_line.line_type {
778 for te in &mut new_line.text_elements {
779 if te.element_type == None
780 && te.text == new_line.scene_number.clone().unwrap_or("_N?N_".to_string())
781 {
782 te.element_type = Some(SPType::SP_SCENENUM);
783 println!("{:?}", te.element_type);
784 }
785 }
786 } else {
787 let mut last_element_type: &Option<SPType> = &None;
791 for te in &mut new_line.text_elements {
792 if te.element_type == None {
793 match new_line.line_type {
794 Some(SPType::SP_ACTION) => {
795 te.element_type = Some(SPType::SP_ACTION);
796 }
797 Some(SPType::SP_CHARACTER) => match last_element_type {
798 Some(SPType::SP_CHARACTER_EXTENSION) => {
799 te.element_type = Some(SPType::SP_CHARACTER_EXTENSION);
800 }
801 _ => {
802 te.element_type = Some(SPType::SP_CHARACTER);
803 }
804 },
805 Some(SPType::SP_DIALOGUE) => {
806 te.element_type = Some(SPType::SP_DIALOGUE);
807 }
808
809 _ => {}
810 }
811 }
812
813 if new_line.line_type == Some(SPType::SP_PAGE_HEADER)
814 && te.element_type == Some(SPType::NON_CONTENT_TOP)
815 {
816 te.element_type = Some(SPType::SP_PAGE_REVISION_LABEL);
817 }
818 last_element_type = &te.element_type
819 }
820 }
821
822 new_page.lines.push(new_line);
823 }
824 if new_page.lines.is_empty() {
825 continue;
826 }
827
828 new_screenplay_doc.pages.push(new_page);
829 }
830
831 Some(new_screenplay_doc)
832}