-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathREADME.Rmd
More file actions
812 lines (425 loc) · 27.9 KB
/
Copy pathREADME.Rmd
File metadata and controls
812 lines (425 loc) · 27.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
---
title: "Projects for Text Version Comparison and Analytics in R"
output:
html_document:
keep_md: yes
number_sections: yes
self_contained: yes
toc: yes
pdf_document:
number_sections: yes
toc: yes
---
```{r setting options, include=FALSE}
library(knitr)
options("width"=101)
tmp <- devtools:::read_dcf("DESCRIPTION")
knitr::opts_chunk$set(message=FALSE)
```
```{r title, results='asis', echo=FALSE, include=FALSE}
cat("#", tmp$Title)
```
# Overview
**Status**
```{r, echo=FALSE, results='asis'}
doc_type <- opts_knit$get("rmarkdown.pandoc.to")
if( !is.null(doc_type) && doc_type=="html" ){
cat(
'
[](https://travis-ci.org/petermeissner/diffrprojects)
[](https://codecov.io/gh/petermeissner/diffrprojects?branch=master)
[](https://cran.r-project.org/package=diffrprojects)
'
)
}
```
```{r count lines of code, include=FALSE}
filelist.R <- list.files("R", recursive = TRUE, pattern="\\.R$", ignore.case = TRUE, full.names = TRUE)
filelist.tests <- list.files("tests", recursive = TRUE, pattern="\\.R$", ignore.case = TRUE, full.names = TRUE)
filelist.cpp <- list.files("src", recursive = TRUE, pattern="\\.cpp$", ignore.case = TRUE, full.names = TRUE)
lines.R <- unlist(lapply(filelist.R, readLines))
lines.tests <- unlist(lapply(filelist.tests, readLines))
lines.cpp <- unlist(lapply(filelist.cpp, readLines))
length.R <-
length(grep("(^\\s*$)|(^\\s*#)|(^\\s*//)", lines.R, value = TRUE, invert = TRUE))
length.tests <-
length(grep("(^\\s*$)|(^\\s*#)|(^\\s*//)", lines.tests, value = TRUE, invert = TRUE))
length.cpp <-
length(grep("(^\\s*$)|(^\\s*#)|(^\\s*//)", lines.cpp, value = TRUE, invert = TRUE))
```
*R code:* `r length.R`<br>
*C++ code:* `r length.cpp`<br>
*test code:* `r length.tests`
**Version**
```{r version, results='asis', echo=FALSE}
cat(tmp$Version)
```
**Description**
```{r description, results='asis', echo=FALSE}
cat(tmp$Description)
```
**Funding**
This software was created as part of the "Institutional Design in Western European Democracies" research project, funded by [DFG (Deutsche Forschungsgemeinschaft)](http://gepris.dfg.de/gepris/projekt/146229116), lead by [Ulrich Sieberer](https://scholar.google.com/citations?user=Q_ImhbkAAAAJ) and based at [University Konstanz](https://www.uni-konstanz.de/).
**License**
```{r licence, results='asis', echo=FALSE}
cat(tmp$License, "<br>")
cat(as.character(eval(parse(text=tmp$Author))))
```
**Citation**
```{r citation1, results='asis', echo=FALSE}
citation("diffrprojects")
```
**BibTex for citing**
```{r citation2, eval=FALSE}
toBibtex(citation("diffrprojects"))
```
**Installation**
stable CRAN version
```{r installation1, eval=FALSE}
install.packages("diffrprojects")
library(rtext)
```
(stable) development version
```{r installation2, eval=FALSE}
standard_repos <- options("repos")$repos
install.packages(
"diffrprojects",
repos = c(standard_repos, "https://petermeissner.github.io/drat/")
)
library(rtext)
```
**Contribution**
Note, that this package uses a Contributor Code of Conduct. By participating in this project you agree to abide by its terms: http://contributor-covenant.org/version/1/0/0/ (basically this should be a place where people get along with each other respectfully and nicely, because it's simply more fun that way for everybody)
Contributions are very much welcome, e.g. in the form of:
- **typo fixing** ([edit file directly on Github](https://help.github.com/articles/editing-files-in-another-user-s-repository/))
- **bug reporting** (file an [issue](https://guides.github.com/features/issues/) - after having searched if the issue came up before - as - if possible - [minimal reproducable example](http://stackoverflow.com/help/mcve))
- **extending help files** (e.g. [edit the respective files directly on Github](https://help.github.com/articles/editing-files-in-another-user-s-repository/) or [fork the package](https://help.github.com/articles/fork-a-repo/) and later on make a [pull request](https://help.github.com/articles/using-pull-requests/); note, that the package use [roxygen2](http://r-pkgs.had.co.nz/man.html) for easing documentation)
- **writing example** (e.g. [edit the respective files directly on Github](https://help.github.com/articles/editing-files-in-another-user-s-repository/) or [fork the package](https://help.github.com/articles/fork-a-repo/) and later on make a [pull request](https://help.github.com/articles/using-pull-requests/); note, that the package use [roxygen2](http://r-pkgs.had.co.nz/man.html) for easing documentation)
- **vignette writing** (file an [issue](https://guides.github.com/features/issues/) first so that we can discuss htings than [fork the package](https://help.github.com/articles/fork-a-repo/) and later on make a [pull request](https://help.github.com/articles/using-pull-requests/))
- **test writing** (have a look at the [test coverage](https://codecov.io/gh/petermeissner/stringb/tree/master/R) than [fork the package](https://help.github.com/articles/fork-a-repo/) and later on make a [pull request](https://help.github.com/articles/using-pull-requests/))
- **feature suggestions** (file an [issue](https://guides.github.com/features/issues/) describing the idea, why this is important, possible alternative solutions and an example)
- **general discussion** of approach and or implementation (file an [issue](https://guides.github.com/features/issues/))
- implementation **improvements** (file an [issue](https://guides.github.com/features/issues/) naming whats to be improved, why and how)
# Usage
## Fast Introduction for the Impatient
For those in a hurry here is a very brief
```{r fast intro, cache=TRUE}
# loading package
library(diffrprojects)
# the first chapter of Robinson Crusoe from three different sources
rcs <- rtext:::testfile(pattern="rc.*ch1.txt", full.names = TRUE)
# creating a new project
dp <- diffrproject$new()
# setting options
dp$options$verbose <- FALSE
# adding texts to the corpus
dp$text_add(text_file = rcs)
dp$text_data(1) %>% head(11)
# linking the files (which file should be compared to which)
dp$text_link()
dp$link %>% as.data.frame()
# calculating text alignments
dp$text_align(tokenizer=text_tokenize_words)
dp$alignment[[1]] %>% head(30)
```
## Creating a Diffrprojects Instance
To create a diffrproject we use the diffrproject creator object - it´s simply an object with a function that knows how to create a project.
Creating a project looks like this:
```{r new project}
library(diffrprojects)
dp <- diffrproject$new()
```
Et violà - we created a first, for now empty, project that we will use throughout the tutorial.
## Some Help Please
To get a better idea about what this thing called *diffrproject* really is, you can consult its help page which gives a broad overview over its capabilities:
```{r getting help, eval=FALSE}
?diffrproject
```
Another way is to call the ls() method. This will present us with a data frame listing, all fields where data is stored and all the methods (aka object specific functions) of our diffrprojects instance. Those methods and fields located in *private* are not for the user to mess around with while non-private (*self* aka public) data fields can be read by the user and public methods can be triggered by the user to manipulate the data or retrieve data in a specific format.
```{r ls method}
dp$ls()
```
The base R class() function furthermore reveals from which classes the diffrproject class inherits:
```{r class}
class(dp)
```
## Adding Texts to Projects
Our diffrproject (`dp`) has one method called `text_add()` that allows to add texts to the project. Basically the method can be used in three different flavors: adding character vectors, adding texts stored on disk, or by adding rtext objects (see rtext package: https://CRAN.R-project.org/package=rtext; rtext objects are the way individual texts are represented within diffrprojects). For each of these used cases there is one option: `text`, `text_file`, `rtext`; respectively.
Below are shown examples using each of these methods:
**adding text files**
```{r text_add files}
test_file1 <- stringb:::test_file("rc_1_ch1.txt")
test_file2 <- stringb:::test_file("rc_2_ch1.txt")
dp$text_add(text_file = c(test_file1, test_file2) )
```
**adding rtext objects**
```{r text_add rtext}
test_file <- stringb:::test_file("rc_1_ch1.txt")
rt <- rtext$new( text_file = test_file)
dp$text_add(rtext = rt)
```
**adding character vectors**
```{r text_add character vector}
test_file1 <- stringb:::test_file("rc_1_ch1.txt")
test_file2 <- stringb:::test_file("rc_2_ch1.txt")
cv <- ""
cv[1] <- text_read(test_file1, NULL)
cv[2] <- text_read(test_file2, NULL)
dp$text_add(text = cv)
```
In the last case make sure to put each text in one separate line. Functions like
readLines() or text_read() read in texts such that each line corresponds to one element in a character vector. With e.g. text_read()'s tokenize parameter to NULL the text will be read in as one long string.
## Piping Methods
Now is a good time to mention a feature of diffrprojects that comes in handy: All functions that do not explicitly extract data (those usually have some 'get' as part of their name) do return the object itself so that one can pipe together a series of method calls.
Consider the following example where we initiate a new diffrprojects instance and add two texts in just one pipe:
```{r piping}
dp <-
diffrproject$
new()$
text_add(text_version_1, name = "version1")$
text_add(text_version_2, name = "version2")
length(dp$text)
```
## Getting Infos About Texts
If we want to get some general overview about the texts gathered in our project, we can use the text_meta_data() method to do so. The method has no parameters and returns a data.frame with several variables informing us about its source, length, encoding used for storage, and its name.
```{r text meta data}
dp$text_meta_data()
```
## Showing Text
If you want to have a look at your texts you may do so by using the text's own text_show methods. Per default this method only shows the first 500 characters, but it can be set to higher numbers as well.
```{r}
dp$text$version1$text_show(length=1000)
dp$text$version2$text_show(length=1000)
```
## Getting And Setting Infos About the Project
Similar to the text_meta_data() method we can access the projects meta data via data fields meta and options. But contrary to the text_meta_data() method that gathers data from all the texts within the project and does not allow for manipulation of the data, the data fields allow reading and writing.
First let us have a look and thereafter turn off the message notification service:
**getting data fields**
```{r options get}
dp$options
```
**setting data fields**
```{r options set}
dp$options$verbose <- FALSE
```
(note, ask is deprecated and only remains for compatibility reasons but has no function anymore)
Now it's time to have a look at the projects meta data. It tells us when the project was created, which path to use for SQLite exports, which path to use for saving data as in RData format and what is the projects id. The id is a hash of a time stamp as well as session information which should ensure uniqueness across space and time.
All these values can be manipulated by the user to her liking.
```{r meta}
dp$meta
dp$meta$file_path = "./diffrproject.RData"
```
## Deleting Texts
Of cause we can not only add texts but delete them from the project as well. For this purpose there is the text_delete() method.
Let's just add two texts and delete one by providing its index number and the second by providing its name to the text_delete() method.
```{r text deletion}
dp$text_add(text = "nonesense", "n1")
dp$text_add(text = "nonesense", "n2")
dp$text_delete(3)
dp$text_delete("n2")
length(dp$text)
names(dp$text)
```
## Defining Relationships Between Texts: Linking
The purpose of diffrprojects is to enable data collection on the difference of texts. Having filled a project with various texts, there are endless possibilities to form pairs of text for comparison and change measurement - where endless actually is equal to: $n^2-n$.
Linking can be done via the text_link method which accepts either index numbers or text names for its from and to arguments (a third argument delete will delete a specified link if set to TRUE).
```{r}
dp$text_link(from = 1, to = 2)
dp$text_link(from = 1, to = 2, delete = TRUE)
```
If no arguments are specified, text_link will link the first text to the second, the third to the fourth, the fourth to the fifths and so on.
```{r}
dp$text_link()
```
To get an idea of what links are currently specified, we can directly access the link data field or/and ask R to transform the list found there into a data.frame.
```{r}
dp$link
dp$link %>% as.data.frame()
```
## Aligning Texts and Measuring Change
At the heart of each diffrproject lies the text_align method. This method compares two texts and tries to align parts of one text with parts of the other text. The first two arguments (`t1` and `t2`) are for specifying which pair of texts to compare - if left as-is, all text pairs that are specified within the link data field will be aligned.
Text parts are arbitrary character spans defined by the `tokenizer` argument. This argument expects a function splitting text into a token data.frame. If the tokenizer argument is left as-is, it will default to text_tokenize_lines function from the stringb package.
Text tokens can be pre-processed before alignment. The `clean` argument allows to hand over a function tranforming a charactr vector of text tokens into their clean counterparts.
The `ignore` arguments expects a function that is able to transform a character vector of tokens into a logical vector of same length, indicating which tokens to ignore throughout the alignment process and which to consider.
The next argument - `distance` - specifies which distance metrics to use to calculate distances between strings.
Since the text_align method basically is a wrapper around diff_align you can get more information via `?diff_align` and since again diff_align is a wrapper around stringdist from the stringdist package `?stringdist::stringdist` and also ``?stringdist::`stringdist-metrics` `` will provide further insights about possible metrics and how to use the rest of the arguments to text_align (these are passed through to stringdist).
Let's have an example using the Levenshtein distance to calculate distances between tokens (lines per default). Furthermore we allow the distance between two aligned tokens to be as large as 15. Tokens which do not find a partner below that distance are considered to have been deleted or respectively inserted. Tokens which find a partner with a non-zero distance which is not above the threshhold are considered changes - transformations of one token into the other.
The following shows the resulting list of alignment data.frames.
```{r}
dp$text_align(distance = "lv", maxDist = 15)
dp$alignment
```
To measure the change between those two texts we can e.g. aggregate the the distances by change type:
```{r}
sum_up_changes <- function(x){
x %>%
dplyr::group_by(type) %>%
dplyr::summarise(sum_of_change = sum(distance))
}
lapply( dp$alignment, sum_up_changes)
```
## Coding Texts
Now let us put some data into our diffrproject.
The most basic method to do so is simply called text_code. Text_code takes up to five arguments (the first three are mandatory), where one specifies the text to be coded (`text`, either by index number or by name), how the variable to store the information is called (`x`), and the index number or a vector of those indicating which characters of the text should be coded. The last two parameters are optional and specify which value the variable should hold (`val`) and at which hierarchy level the coding is placed (`hl`, higher or equal hierarchy levels will overwrite existing codings of lower hierarchy level for the same text, character span, and variable).
```{r}
dp$text_code(text = 1, x = "start", i=1:5, val = TRUE, hl = 0)
dp$text_code(text = "version2", x = "start", i=1:5, val = TRUE, hl = 0)
```
The text_code method is quite verbose and in most cases more suited to be accessed by a machine or algorithm than by a human. Therefore, there are three other methods to code text: text_code_regex, text_code_alignment_token, text_code_alignment_token_regex.
The text_code_regex method allows to search for text patterns and code a whole pattern instead of assigning codes character by character - the `i` argument of text_code gets replaced by a `pattern` argument. The in addition further arguments can be passed to the pattern search functions via `...` - see e.g. `?grep` for possible further arguments and https://stat.ethz.ch/R-manual/R-devel/library/base/html/regex.html for a description of regular expressions in R.
In this example we are searching for the word *"it"* in text 1 and code each instance.
```{r}
dp$text_code_regex(text = 1, x = "it", pattern = "\\bit\\b", ignore.case=TRUE)
```
Another variant of coding text is by using alignment tokens. Having alignment data availible, this allows for selecting: link, alignment and text while the other arguments from above stay the same.
```{r}
# having a look at alignment number 4
dp$alignment[[1]][4,]
# coding text connected by alignment number 4
dp$text_code_alignment_token(
link = 1,
alignment_i = 4,
text1 = TRUE,
text2 = TRUE,
x = "token_coding",
val = 4,
hl = 0
)
```
## Getting Text Codings
The most basic way to get text data is to use the text_data method. This method will go through all or only selected texts, gather all the data stored there and put it into a neat data.frame where name identifies the text from which the data comes per name, char informs us about the character that was coded, and i refers to the characters position within the text. All other variables hold the data we added during the examples above.
```{r}
dp$text_data(text = 1) %>% head()
```
## Aggregating Text Codings
The usage of text_data has its merits but often one is more interested in text data aggregated to a specific level. The following three aggregation functions offer a solution to this problem: tokenize_text_data_lines, tokenize_text_data_words, and tokenize_text_data_regex. These three methods make use of the similiary named methods provided by the rtext package.
One important thing to keep in mind is that using these methods implies aggregating several data values on character level into one data value at token level. Therefore there has to be some aggregation function to be involved. The default is to use the value that occurs most often on character level, if more than one distinct values occur more than once the first is choosen.
The aggregation function can be changed to whatever function the user seems appropriate by passing it to `aggregate_function` - as long as it reduces a vector of values into a vector with only one value.
The `join` argument allows to decide how text and data are joined into the resulting data.frame - left: all token, right: all data, full: token with or without data and data with or without token.
```{r}
dp$tokenize_text_data_lines(
text = 1,
join = "right",
aggregate_function =
function(x){
paste(x[1:3], collapse = ",")
}
)
```
## Text Coding Inheritence
Having aligned two texts via token pairs another functionality of diffrprojects becomes availible: text coding inheritance via no-change tokens. This means that text codings can get copied to those tokens they are aligned with, given that they are considered the same - i.e. the distance equals zero and the change type therefore is no-change.
To show this feature we use the text_inherit method and we will start with a fresh example. A new project with two texts. The first text gets some codings, then they are aligned, and in a last step codings are transfered from one text to the other via the text_data_inherit method.
```{r}
dp <-
diffrproject$new()$
text_add(text_version_1)$
text_add(text_version_2)$
text_code_regex(
text = 1,
x = "test1",
pattern = "This part.*?change",
val = "inherited"
)$
text_code_regex(
text = 1,
x = "test2",
pattern = "This part.*?change",
val = "inherited"
)
dp$tokenize_text_data_lines(1)
dp$
text_link()$
text_align()$
text_data_inherit(
link = 1,
direction = "forward"
)
dp$tokenize_text_data_lines(2)
```
## Saving and Loading Projects
Diffrprojects also allow for storing and loading project to and from disk.
```{r, eval=FALSE}
# save to file
dp$save(file = "dp_save.RData")
# remove object
rm(dp)
# create new object and load saved data into new object
dp <- diffrproject$new()
dp$load("dp_save.RData")
```
```{r}
dp$tokenize_text_data_lines(2)
```
# Diffrprojectswidget a Diffrprojects Extension
```{r, include=FALSE}
dpw <- require(diffrprojectswidget)
wbs <- require(webshot)
dpw <- dpw & wbs
```
```{r, eval=dpw}
library(diffrprojectswidget)
dp_table(dp, 1, height = 800, width = "100%")
```
```{r, eval=dpw}
library(diffrprojectswidget)
dp_vis(dp, 1, height = 300)
```
# Technicalities
## Naming Conventions and General Structure of Methods and Data
The methods and data fields of diffrprojects can be categorized into five realms - *cursive*: methods; (parentheses): private; rest: data:
- **text**: everything related to individual texts starts with text
- text, *text_add*, *text_delete*, *text_align*, *text_code*, *text_code_alignment_token*, *text_code_alignment_token_regex*, *text_code_regex*,
- *text_data*, *text_data_inherit*, *tokenize_text_data_lines*, *tokenize_text_data_regex*, *tokenize_text_data_words*
- text_meta_data
- **alignment**: everything that concerns the relation between two texts
- alignment, *alignment_add*, *alignment_code*, *alignment_delete*, *alignemtn_data_full*, *alignment_data_set*
- text_link, *link*
- **misc**:
- meta, options, *load*, *save*, *export_sqlite*, *import_sqlite*, (*execute_load*), (*prepare_save*)
- **inherited from R6_rtext_extended**:
- options, *message*, *warning*, (*hash*), (hashed), (hashes)
- **inherited from R6**:
- *clone*, *initialize*
## Data formats
### meta
Meta is a list with only a few items providing/storing general information for the whole project - i.e. time stamp the project was created, path to store data, path to export data, an project id.
### text
Text is a list of rtext instances. Each rtext instance stores text's actual text as data gathered on the text.
The text_data method will return a data.frame containing all text data, while tokenize_text_data_xxx methods will aggregate text data to specific token levels: words, lines or user defined patterns.
### link
Link is a list of links between texts. Link defines for which text combination alignments should be calculated. Each list item hold a from and to field which stores the names of texts to be aligned. The method to create links is text_link, it also allows to delete specific links.
Link data can be transformed to one big data.frame via: as.data.frame function.
### alignment
Alignment is a list of data.frames. Each alignment list item stores which part of one text (character span) is connected to which part of another text (character span).
The list of alignments can be transformed to one big data.frame via: as.data.frame function.
### alignment_data
Alignment_data is a list of dataframes.
## The Diffrprojects Universe
Diffrprojects has two other packages it relies heavily on and one package that adds further features.
### Rtext
Rtext is a package providing a data structure and accompanying methods to handle texts / strings / characters as well as data bound to these texts / strings / characters. All string manipulations are based upon the stringb package. All diffrproject texts are actually rtext instances. Unfortunate you cannot yet manipulate rtext objects once they are part of a diffrproject and expect that data on the relation between texts (i.e. alignment and alignment_data) gets updated as well - hence manipulating texts might lead to inconsistencies in alignments and alignment_data.
A strategy to implement such a feature would be to extend rtext in such a way that text manipulation methods would pass change information to a list of call back functions. Furthermore, diffrprojects need two methods that allow for handling shifts in the character sequences of texts. Those update methods can then be passed to rtext instances once they become part of a diffrproject. Then whenever e.g. some characters are deleted, alignments as well as alignment data touching these character spans get deleted as well and character span information for all other alignments get shifted by the appropriate amount.
For those preferring a version using stringi/stringr - go ahead - since rtext and diffrprojects provide tests for all respectively for all vital parts and stringb copied the function naming scheme from stringr anyways, this should be a small matter.
### Stringb
Stringb is a package providing convenience functions for string handling and manipulation using R's own regular expression engine. All string manipulations are based upon the stringb package.
In addition stringb provides very flexible text tokenization functions that are very much in line with the needs of diffrprojects.
### Diffrprojectswidget
This package enhances diffrprojects by providing HTMLwidgets for visualizing diffrproject data: as interactive table or as interactive graph.
HTMLwidgets (see: http://www.htmlwidgets.org/) are a framework that allows for interactive, web technology based graphics that are furthermore easily integrate able into e.g. R-shiny (http://shiny.rstudio.com/) applications.
## Two words or more about Objects / R6 / Classes / Instances
Diffrprojects is written in object oriented programming style because it seemed adequate to do so. Why? Because in OOP in comparison to functional programming one does more stuff like in-place-modification of data, data and its modifiers (methods) come in one big bundle, it´s easier to work on the current state of the object / to only allow consistent states of the object. Yeap everything here could have done with FP as well - please go ahead.
The downside of using OOP in R is that what happens becomes much more intrasparent and harder to reason about - I am sorry for that.
### Classes and Instances
Classes are object blueprints - a schema that describes how an object of this class should look like. Classes might be objects too, but they are not the objects they describe. To get an object instance of an object - a manifestion of the idea of the object described in the class - one has to explicitly translate execute the instructions led out in the class, e.g. via: `diffrproject$new()`, or `rtext$new()`
### R6
R6 is a package that provides a framework that makes it very, very easy to build objects in R that are more like things known from traditional all purpose programming languages like Java or C++.
### Methods
Methods are exactly like functions, only that they are not floating around loosely in your global environment or elsewhere, but are bound to specific instances of an object. So there is not one text_add function that can be used with any diffrproject, but there is one specific text_add method for each instance of an diffrproject. This sounds quite strange, right? Why the duplication? Well, with that you can e.g. pass this method around, hand it over to a function that calls it or put it into another object maybe that than can decide to use it or not. A silly example:
```{r}
dp1 <- diffrproject$new()
add_text_to_dp1 <- dp1$text_add
add_text_to_dp1("ahhh")
add_text_to_dp1("behhh")
add_text_to_dp1("cehhh")
names(dp1$text)
```