diff --git a/Diff/Diff.php b/Diff/Diff.php new file mode 100644 index 0000000..db920a8 --- /dev/null +++ b/Diff/Diff.php @@ -0,0 +1,453 @@ +, and is used/adapted with his permission. + * + * $Horde: framework/Text_Diff/Diff.php,v 1.11.2.12 2009/01/06 15:23:41 jan Exp $ + * + * Copyright 2004 Geoffrey T. Dairiki + * Copyright 2004-2009 The Horde Project (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (LGPL). If you did + * not receive this file, see http://opensource.org/licenses/lgpl-license.php. + * + * @package Text_Diff + * @author Geoffrey T. Dairiki + */ +class Text_Diff { + + /** + * Array of changes. + * + * @var array + */ + var $_edits; + + /** + * Computes diffs between sequences of strings. + * + * @param string $engine Name of the diffing engine to use. 'auto' + * will automatically select the best. + * @param array $params Parameters to pass to the diffing engine. + * Normally an array of two arrays, each + * containing the lines from a file. + */ + function Text_Diff($engine, $params) + { + // Backward compatibility workaround. + if (!is_string($engine)) { + $params = array($engine, $params); + $engine = 'auto'; + } + + if ($engine == 'auto') { + $engine = extension_loaded('xdiff') ? 'xdiff' : 'native'; + } else { + $engine = basename($engine); + } + + require_once 'Text/Diff/Engine/' . $engine . '.php'; + $class = 'Text_Diff_Engine_' . $engine; + $diff_engine = new $class(); + + $this->_edits = call_user_func_array(array($diff_engine, 'diff'), $params); + } + + /** + * Returns the array of differences. + */ + function getDiff() + { + return $this->_edits; + } + + /** + * returns the number of new (added) lines in a given diff. + * + * @since Text_Diff 1.1.0 + * @since Horde 3.2 + * + * @return integer The number of new lines + */ + function countAddedLines() + { + $count = 0; + foreach ($this->_edits as $edit) { + if (is_a($edit, 'Text_Diff_Op_add') || + is_a($edit, 'Text_Diff_Op_change')) { + $count += $edit->nfinal(); + } + } + return $count; + } + + /** + * Returns the number of deleted (removed) lines in a given diff. + * + * @since Text_Diff 1.1.0 + * @since Horde 3.2 + * + * @return integer The number of deleted lines + */ + function countDeletedLines() + { + $count = 0; + foreach ($this->_edits as $edit) { + if (is_a($edit, 'Text_Diff_Op_delete') || + is_a($edit, 'Text_Diff_Op_change')) { + $count += $edit->norig(); + } + } + return $count; + } + + /** + * Computes a reversed diff. + * + * Example: + * + * $diff = new Text_Diff($lines1, $lines2); + * $rev = $diff->reverse(); + * + * + * @return Text_Diff A Diff object representing the inverse of the + * original diff. Note that we purposely don't return a + * reference here, since this essentially is a clone() + * method. + */ + function reverse() + { + if (version_compare(zend_version(), '2', '>')) { + $rev = clone($this); + } else { + $rev = $this; + } + $rev->_edits = array(); + foreach ($this->_edits as $edit) { + $rev->_edits[] = $edit->reverse(); + } + return $rev; + } + + /** + * Checks for an empty diff. + * + * @return boolean True if two sequences were identical. + */ + function isEmpty() + { + foreach ($this->_edits as $edit) { + if (!is_a($edit, 'Text_Diff_Op_copy')) { + return false; + } + } + return true; + } + + /** + * Computes the length of the Longest Common Subsequence (LCS). + * + * This is mostly for diagnostic purposes. + * + * @return integer The length of the LCS. + */ + function lcs() + { + $lcs = 0; + foreach ($this->_edits as $edit) { + if (is_a($edit, 'Text_Diff_Op_copy')) { + $lcs += count($edit->orig); + } + } + return $lcs; + } + + /** + * Gets the original set of lines. + * + * This reconstructs the $from_lines parameter passed to the constructor. + * + * @return array The original sequence of strings. + */ + function getOriginal() + { + $lines = array(); + foreach ($this->_edits as $edit) { + if ($edit->orig) { + array_splice($lines, count($lines), 0, $edit->orig); + } + } + return $lines; + } + + /** + * Gets the final set of lines. + * + * This reconstructs the $to_lines parameter passed to the constructor. + * + * @return array The sequence of strings. + */ + function getFinal() + { + $lines = array(); + foreach ($this->_edits as $edit) { + if ($edit->final) { + array_splice($lines, count($lines), 0, $edit->final); + } + } + return $lines; + } + + /** + * Removes trailing newlines from a line of text. This is meant to be used + * with array_walk(). + * + * @param string $line The line to trim. + * @param integer $key The index of the line in the array. Not used. + */ + function trimNewlines(&$line, $key) + { + $line = str_replace(array("\n", "\r"), '', $line); + } + + /** + * Determines the location of the system temporary directory. + * + * @static + * + * @access protected + * + * @return string A directory name which can be used for temp files. + * Returns false if one could not be found. + */ + function _getTempDir() + { + $tmp_locations = array('/tmp', '/var/tmp', 'c:\WUTemp', 'c:\temp', + 'c:\windows\temp', 'c:\winnt\temp'); + + /* Try PHP's upload_tmp_dir directive. */ + $tmp = ini_get('upload_tmp_dir'); + + /* Otherwise, try to determine the TMPDIR environment variable. */ + if (!strlen($tmp)) { + $tmp = getenv('TMPDIR'); + } + + /* If we still cannot determine a value, then cycle through a list of + * preset possibilities. */ + while (!strlen($tmp) && count($tmp_locations)) { + $tmp_check = array_shift($tmp_locations); + if (@is_dir($tmp_check)) { + $tmp = $tmp_check; + } + } + + /* If it is still empty, we have failed, so return false; otherwise + * return the directory determined. */ + return strlen($tmp) ? $tmp : false; + } + + /** + * Checks a diff for validity. + * + * This is here only for debugging purposes. + */ + function _check($from_lines, $to_lines) + { + if (serialize($from_lines) != serialize($this->getOriginal())) { + trigger_error("Reconstructed original doesn't match", E_USER_ERROR); + } + if (serialize($to_lines) != serialize($this->getFinal())) { + trigger_error("Reconstructed final doesn't match", E_USER_ERROR); + } + + $rev = $this->reverse(); + if (serialize($to_lines) != serialize($rev->getOriginal())) { + trigger_error("Reversed original doesn't match", E_USER_ERROR); + } + if (serialize($from_lines) != serialize($rev->getFinal())) { + trigger_error("Reversed final doesn't match", E_USER_ERROR); + } + + $prevtype = null; + foreach ($this->_edits as $edit) { + if ($prevtype == get_class($edit)) { + trigger_error("Edit sequence is non-optimal", E_USER_ERROR); + } + $prevtype = get_class($edit); + } + + return true; + } + +} + +/** + * @package Text_Diff + * @author Geoffrey T. Dairiki + */ +class Text_MappedDiff extends Text_Diff { + + /** + * Computes a diff between sequences of strings. + * + * This can be used to compute things like case-insensitve diffs, or diffs + * which ignore changes in white-space. + * + * @param array $from_lines An array of strings. + * @param array $to_lines An array of strings. + * @param array $mapped_from_lines This array should have the same size + * number of elements as $from_lines. The + * elements in $mapped_from_lines and + * $mapped_to_lines are what is actually + * compared when computing the diff. + * @param array $mapped_to_lines This array should have the same number + * of elements as $to_lines. + */ + function Text_MappedDiff($from_lines, $to_lines, + $mapped_from_lines, $mapped_to_lines) + { + assert(count($from_lines) == count($mapped_from_lines)); + assert(count($to_lines) == count($mapped_to_lines)); + + parent::Text_Diff($mapped_from_lines, $mapped_to_lines); + + $xi = $yi = 0; + for ($i = 0; $i < count($this->_edits); $i++) { + $orig = &$this->_edits[$i]->orig; + if (is_array($orig)) { + $orig = array_slice($from_lines, $xi, count($orig)); + $xi += count($orig); + } + + $final = &$this->_edits[$i]->final; + if (is_array($final)) { + $final = array_slice($to_lines, $yi, count($final)); + $yi += count($final); + } + } + } + +} + +/** + * @package Text_Diff + * @author Geoffrey T. Dairiki + * + * @access private + */ +class Text_Diff_Op { + + var $orig; + var $final; + + function &reverse() + { + trigger_error('Abstract method', E_USER_ERROR); + } + + function norig() + { + return $this->orig ? count($this->orig) : 0; + } + + function nfinal() + { + return $this->final ? count($this->final) : 0; + } + +} + +/** + * @package Text_Diff + * @author Geoffrey T. Dairiki + * + * @access private + */ +class Text_Diff_Op_copy extends Text_Diff_Op { + + function Text_Diff_Op_copy($orig, $final = false) + { + if (!is_array($final)) { + $final = $orig; + } + $this->orig = $orig; + $this->final = $final; + } + + function &reverse() + { + $reverse = new Text_Diff_Op_copy($this->final, $this->orig); + return $reverse; + } + +} + +/** + * @package Text_Diff + * @author Geoffrey T. Dairiki + * + * @access private + */ +class Text_Diff_Op_delete extends Text_Diff_Op { + + function Text_Diff_Op_delete($lines) + { + $this->orig = $lines; + $this->final = false; + } + + function &reverse() + { + $reverse = new Text_Diff_Op_add($this->orig); + return $reverse; + } + +} + +/** + * @package Text_Diff + * @author Geoffrey T. Dairiki + * + * @access private + */ +class Text_Diff_Op_add extends Text_Diff_Op { + + function Text_Diff_Op_add($lines) + { + $this->final = $lines; + $this->orig = false; + } + + function &reverse() + { + $reverse = new Text_Diff_Op_delete($this->final); + return $reverse; + } + +} + +/** + * @package Text_Diff + * @author Geoffrey T. Dairiki + * + * @access private + */ +class Text_Diff_Op_change extends Text_Diff_Op { + + function Text_Diff_Op_change($orig, $final) + { + $this->orig = $orig; + $this->final = $final; + } + + function &reverse() + { + $reverse = new Text_Diff_Op_change($this->final, $this->orig); + return $reverse; + } + +} diff --git a/Diff/Diff/Engine/native.php b/Diff/Diff/Engine/native.php new file mode 100644 index 0000000..84168c0 --- /dev/null +++ b/Diff/Diff/Engine/native.php @@ -0,0 +1,438 @@ + 2, and some optimizations) are from + * Geoffrey T. Dairiki . The original PHP version of this + * code was written by him, and is used/adapted with his permission. + * + * $Horde: framework/Text_Diff/Diff/Engine/native.php,v 1.7.2.5 2009/01/06 15:23:41 jan Exp $ + * + * Copyright 2004-2009 The Horde Project (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (LGPL). If you did + * not receive this file, see http://opensource.org/licenses/lgpl-license.php. + * + * @author Geoffrey T. Dairiki + * @package Text_Diff + */ +class Text_Diff_Engine_native { + + function diff($from_lines, $to_lines) + { + array_walk($from_lines, array('Text_Diff', 'trimNewlines')); + array_walk($to_lines, array('Text_Diff', 'trimNewlines')); + + $n_from = count($from_lines); + $n_to = count($to_lines); + + $this->xchanged = $this->ychanged = array(); + $this->xv = $this->yv = array(); + $this->xind = $this->yind = array(); + unset($this->seq); + unset($this->in_seq); + unset($this->lcs); + + // Skip leading common lines. + for ($skip = 0; $skip < $n_from && $skip < $n_to; $skip++) { + if ($from_lines[$skip] !== $to_lines[$skip]) { + break; + } + $this->xchanged[$skip] = $this->ychanged[$skip] = false; + } + + // Skip trailing common lines. + $xi = $n_from; $yi = $n_to; + for ($endskip = 0; --$xi > $skip && --$yi > $skip; $endskip++) { + if ($from_lines[$xi] !== $to_lines[$yi]) { + break; + } + $this->xchanged[$xi] = $this->ychanged[$yi] = false; + } + + // Ignore lines which do not exist in both files. + for ($xi = $skip; $xi < $n_from - $endskip; $xi++) { + $xhash[$from_lines[$xi]] = 1; + } + for ($yi = $skip; $yi < $n_to - $endskip; $yi++) { + $line = $to_lines[$yi]; + if (($this->ychanged[$yi] = empty($xhash[$line]))) { + continue; + } + $yhash[$line] = 1; + $this->yv[] = $line; + $this->yind[] = $yi; + } + for ($xi = $skip; $xi < $n_from - $endskip; $xi++) { + $line = $from_lines[$xi]; + if (($this->xchanged[$xi] = empty($yhash[$line]))) { + continue; + } + $this->xv[] = $line; + $this->xind[] = $xi; + } + + // Find the LCS. + $this->_compareseq(0, count($this->xv), 0, count($this->yv)); + + // Merge edits when possible. + $this->_shiftBoundaries($from_lines, $this->xchanged, $this->ychanged); + $this->_shiftBoundaries($to_lines, $this->ychanged, $this->xchanged); + + // Compute the edit operations. + $edits = array(); + $xi = $yi = 0; + while ($xi < $n_from || $yi < $n_to) { + assert($yi < $n_to || $this->xchanged[$xi]); + assert($xi < $n_from || $this->ychanged[$yi]); + + // Skip matching "snake". + $copy = array(); + while ($xi < $n_from && $yi < $n_to + && !$this->xchanged[$xi] && !$this->ychanged[$yi]) { + $copy[] = $from_lines[$xi++]; + ++$yi; + } + if ($copy) { + $edits[] = &new Text_Diff_Op_copy($copy); + } + + // Find deletes & adds. + $delete = array(); + while ($xi < $n_from && $this->xchanged[$xi]) { + $delete[] = $from_lines[$xi++]; + } + + $add = array(); + while ($yi < $n_to && $this->ychanged[$yi]) { + $add[] = $to_lines[$yi++]; + } + + if ($delete && $add) { + $edits[] = &new Text_Diff_Op_change($delete, $add); + } elseif ($delete) { + $edits[] = &new Text_Diff_Op_delete($delete); + } elseif ($add) { + $edits[] = &new Text_Diff_Op_add($add); + } + } + + return $edits; + } + + /** + * Divides the Largest Common Subsequence (LCS) of the sequences (XOFF, + * XLIM) and (YOFF, YLIM) into NCHUNKS approximately equally sized + * segments. + * + * Returns (LCS, PTS). LCS is the length of the LCS. PTS is an array of + * NCHUNKS+1 (X, Y) indexes giving the diving points between sub + * sequences. The first sub-sequence is contained in (X0, X1), (Y0, Y1), + * the second in (X1, X2), (Y1, Y2) and so on. Note that (X0, Y0) == + * (XOFF, YOFF) and (X[NCHUNKS], Y[NCHUNKS]) == (XLIM, YLIM). + * + * This function assumes that the first lines of the specified portions of + * the two files do not match, and likewise that the last lines do not + * match. The caller must trim matching lines from the beginning and end + * of the portions it is going to specify. + */ + function _diag ($xoff, $xlim, $yoff, $ylim, $nchunks) + { + $flip = false; + + if ($xlim - $xoff > $ylim - $yoff) { + /* Things seems faster (I'm not sure I understand why) when the + * shortest sequence is in X. */ + $flip = true; + list ($xoff, $xlim, $yoff, $ylim) + = array($yoff, $ylim, $xoff, $xlim); + } + + if ($flip) { + for ($i = $ylim - 1; $i >= $yoff; $i--) { + $ymatches[$this->xv[$i]][] = $i; + } + } else { + for ($i = $ylim - 1; $i >= $yoff; $i--) { + $ymatches[$this->yv[$i]][] = $i; + } + } + + $this->lcs = 0; + $this->seq[0]= $yoff - 1; + $this->in_seq = array(); + $ymids[0] = array(); + + $numer = $xlim - $xoff + $nchunks - 1; + $x = $xoff; + for ($chunk = 0; $chunk < $nchunks; $chunk++) { + if ($chunk > 0) { + for ($i = 0; $i <= $this->lcs; $i++) { + $ymids[$i][$chunk - 1] = $this->seq[$i]; + } + } + + $x1 = $xoff + (int)(($numer + ($xlim - $xoff) * $chunk) / $nchunks); + for (; $x < $x1; $x++) { + $line = $flip ? $this->yv[$x] : $this->xv[$x]; + if (empty($ymatches[$line])) { + continue; + } + $matches = $ymatches[$line]; + reset($matches); + while (list(, $y) = each($matches)) { + if (empty($this->in_seq[$y])) { + $k = $this->_lcsPos($y); + assert($k > 0); + $ymids[$k] = $ymids[$k - 1]; + break; + } + } + while (list(, $y) = each($matches)) { + if ($y > $this->seq[$k - 1]) { + assert($y <= $this->seq[$k]); + /* Optimization: this is a common case: next match is + * just replacing previous match. */ + $this->in_seq[$this->seq[$k]] = false; + $this->seq[$k] = $y; + $this->in_seq[$y] = 1; + } elseif (empty($this->in_seq[$y])) { + $k = $this->_lcsPos($y); + assert($k > 0); + $ymids[$k] = $ymids[$k - 1]; + } + } + } + } + + $seps[] = $flip ? array($yoff, $xoff) : array($xoff, $yoff); + $ymid = $ymids[$this->lcs]; + for ($n = 0; $n < $nchunks - 1; $n++) { + $x1 = $xoff + (int)(($numer + ($xlim - $xoff) * $n) / $nchunks); + $y1 = $ymid[$n] + 1; + $seps[] = $flip ? array($y1, $x1) : array($x1, $y1); + } + $seps[] = $flip ? array($ylim, $xlim) : array($xlim, $ylim); + + return array($this->lcs, $seps); + } + + function _lcsPos($ypos) + { + $end = $this->lcs; + if ($end == 0 || $ypos > $this->seq[$end]) { + $this->seq[++$this->lcs] = $ypos; + $this->in_seq[$ypos] = 1; + return $this->lcs; + } + + $beg = 1; + while ($beg < $end) { + $mid = (int)(($beg + $end) / 2); + if ($ypos > $this->seq[$mid]) { + $beg = $mid + 1; + } else { + $end = $mid; + } + } + + assert($ypos != $this->seq[$end]); + + $this->in_seq[$this->seq[$end]] = false; + $this->seq[$end] = $ypos; + $this->in_seq[$ypos] = 1; + return $end; + } + + /** + * Finds LCS of two sequences. + * + * The results are recorded in the vectors $this->{x,y}changed[], by + * storing a 1 in the element for each line that is an insertion or + * deletion (ie. is not in the LCS). + * + * The subsequence of file 0 is (XOFF, XLIM) and likewise for file 1. + * + * Note that XLIM, YLIM are exclusive bounds. All line numbers are + * origin-0 and discarded lines are not counted. + */ + function _compareseq ($xoff, $xlim, $yoff, $ylim) + { + /* Slide down the bottom initial diagonal. */ + while ($xoff < $xlim && $yoff < $ylim + && $this->xv[$xoff] == $this->yv[$yoff]) { + ++$xoff; + ++$yoff; + } + + /* Slide up the top initial diagonal. */ + while ($xlim > $xoff && $ylim > $yoff + && $this->xv[$xlim - 1] == $this->yv[$ylim - 1]) { + --$xlim; + --$ylim; + } + + if ($xoff == $xlim || $yoff == $ylim) { + $lcs = 0; + } else { + /* This is ad hoc but seems to work well. $nchunks = + * sqrt(min($xlim - $xoff, $ylim - $yoff) / 2.5); $nchunks = + * max(2,min(8,(int)$nchunks)); */ + $nchunks = min(7, $xlim - $xoff, $ylim - $yoff) + 1; + list($lcs, $seps) + = $this->_diag($xoff, $xlim, $yoff, $ylim, $nchunks); + } + + if ($lcs == 0) { + /* X and Y sequences have no common subsequence: mark all + * changed. */ + while ($yoff < $ylim) { + $this->ychanged[$this->yind[$yoff++]] = 1; + } + while ($xoff < $xlim) { + $this->xchanged[$this->xind[$xoff++]] = 1; + } + } else { + /* Use the partitions to split this problem into subproblems. */ + reset($seps); + $pt1 = $seps[0]; + while ($pt2 = next($seps)) { + $this->_compareseq ($pt1[0], $pt2[0], $pt1[1], $pt2[1]); + $pt1 = $pt2; + } + } + } + + /** + * Adjusts inserts/deletes of identical lines to join changes as much as + * possible. + * + * We do something when a run of changed lines include a line at one end + * and has an excluded, identical line at the other. We are free to + * choose which identical line is included. `compareseq' usually chooses + * the one at the beginning, but usually it is cleaner to consider the + * following identical line to be the "change". + * + * This is extracted verbatim from analyze.c (GNU diffutils-2.7). + */ + function _shiftBoundaries($lines, &$changed, $other_changed) + { + $i = 0; + $j = 0; + + assert('count($lines) == count($changed)'); + $len = count($lines); + $other_len = count($other_changed); + + while (1) { + /* Scan forward to find the beginning of another run of + * changes. Also keep track of the corresponding point in the + * other file. + * + * Throughout this code, $i and $j are adjusted together so that + * the first $i elements of $changed and the first $j elements of + * $other_changed both contain the same number of zeros (unchanged + * lines). + * + * Furthermore, $j is always kept so that $j == $other_len or + * $other_changed[$j] == false. */ + while ($j < $other_len && $other_changed[$j]) { + $j++; + } + + while ($i < $len && ! $changed[$i]) { + assert('$j < $other_len && ! $other_changed[$j]'); + $i++; $j++; + while ($j < $other_len && $other_changed[$j]) { + $j++; + } + } + + if ($i == $len) { + break; + } + + $start = $i; + + /* Find the end of this run of changes. */ + while (++$i < $len && $changed[$i]) { + continue; + } + + do { + /* Record the length of this run of changes, so that we can + * later determine whether the run has grown. */ + $runlength = $i - $start; + + /* Move the changed region back, so long as the previous + * unchanged line matches the last changed one. This merges + * with previous changed regions. */ + while ($start > 0 && $lines[$start - 1] == $lines[$i - 1]) { + $changed[--$start] = 1; + $changed[--$i] = false; + while ($start > 0 && $changed[$start - 1]) { + $start--; + } + assert('$j > 0'); + while ($other_changed[--$j]) { + continue; + } + assert('$j >= 0 && !$other_changed[$j]'); + } + + /* Set CORRESPONDING to the end of the changed run, at the + * last point where it corresponds to a changed run in the + * other file. CORRESPONDING == LEN means no such point has + * been found. */ + $corresponding = $j < $other_len ? $i : $len; + + /* Move the changed region forward, so long as the first + * changed line matches the following unchanged one. This + * merges with following changed regions. Do this second, so + * that if there are no merges, the changed region is moved + * forward as far as possible. */ + while ($i < $len && $lines[$start] == $lines[$i]) { + $changed[$start++] = false; + $changed[$i++] = 1; + while ($i < $len && $changed[$i]) { + $i++; + } + + assert('$j < $other_len && ! $other_changed[$j]'); + $j++; + if ($j < $other_len && $other_changed[$j]) { + $corresponding = $i; + while ($j < $other_len && $other_changed[$j]) { + $j++; + } + } + } + } while ($runlength != $i - $start); + + /* If possible, move the fully-merged run of changes back to a + * corresponding run in the other file. */ + while ($corresponding < $i) { + $changed[--$start] = 1; + $changed[--$i] = 0; + assert('$j > 0'); + while ($other_changed[--$j]) { + continue; + } + assert('$j >= 0 && !$other_changed[$j]'); + } + } + } + +} diff --git a/Diff/Diff/Engine/shell.php b/Diff/Diff/Engine/shell.php new file mode 100644 index 0000000..7f858cb --- /dev/null +++ b/Diff/Diff/Engine/shell.php @@ -0,0 +1,164 @@ + + * @package Text_Diff + * @since 0.3.0 + */ +class Text_Diff_Engine_shell { + + /** + * Path to the diff executable + * + * @var string + */ + var $_diffCommand = 'diff'; + + /** + * Returns the array of differences. + * + * @param array $from_lines lines of text from old file + * @param array $to_lines lines of text from new file + * + * @return array all changes made (array with Text_Diff_Op_* objects) + */ + function diff($from_lines, $to_lines) + { + array_walk($from_lines, array('Text_Diff', 'trimNewlines')); + array_walk($to_lines, array('Text_Diff', 'trimNewlines')); + + $temp_dir = Text_Diff::_getTempDir(); + + // Execute gnu diff or similar to get a standard diff file. + $from_file = tempnam($temp_dir, 'Text_Diff'); + $to_file = tempnam($temp_dir, 'Text_Diff'); + $fp = fopen($from_file, 'w'); + fwrite($fp, implode("\n", $from_lines)); + fclose($fp); + $fp = fopen($to_file, 'w'); + fwrite($fp, implode("\n", $to_lines)); + fclose($fp); + $diff = shell_exec($this->_diffCommand . ' ' . $from_file . ' ' . $to_file); + unlink($from_file); + unlink($to_file); + + if (is_null($diff)) { + // No changes were made + return array(new Text_Diff_Op_copy($from_lines)); + } + + $from_line_no = 1; + $to_line_no = 1; + $edits = array(); + + // Get changed lines by parsing something like: + // 0a1,2 + // 1,2c4,6 + // 1,5d6 + preg_match_all('#^(\d+)(?:,(\d+))?([adc])(\d+)(?:,(\d+))?$#m', $diff, + $matches, PREG_SET_ORDER); + + foreach ($matches as $match) { + if (!isset($match[5])) { + // This paren is not set every time (see regex). + $match[5] = false; + } + + if ($match[3] == 'a') { + $from_line_no--; + } + + if ($match[3] == 'd') { + $to_line_no--; + } + + if ($from_line_no < $match[1] || $to_line_no < $match[4]) { + // copied lines + assert('$match[1] - $from_line_no == $match[4] - $to_line_no'); + array_push($edits, + new Text_Diff_Op_copy( + $this->_getLines($from_lines, $from_line_no, $match[1] - 1), + $this->_getLines($to_lines, $to_line_no, $match[4] - 1))); + } + + switch ($match[3]) { + case 'd': + // deleted lines + array_push($edits, + new Text_Diff_Op_delete( + $this->_getLines($from_lines, $from_line_no, $match[2]))); + $to_line_no++; + break; + + case 'c': + // changed lines + array_push($edits, + new Text_Diff_Op_change( + $this->_getLines($from_lines, $from_line_no, $match[2]), + $this->_getLines($to_lines, $to_line_no, $match[5]))); + break; + + case 'a': + // added lines + array_push($edits, + new Text_Diff_Op_add( + $this->_getLines($to_lines, $to_line_no, $match[5]))); + $from_line_no++; + break; + } + } + + if (!empty($from_lines)) { + // Some lines might still be pending. Add them as copied + array_push($edits, + new Text_Diff_Op_copy( + $this->_getLines($from_lines, $from_line_no, + $from_line_no + count($from_lines) - 1), + $this->_getLines($to_lines, $to_line_no, + $to_line_no + count($to_lines) - 1))); + } + + return $edits; + } + + /** + * Get lines from either the old or new text + * + * @access private + * + * @param array &$text_lines Either $from_lines or $to_lines + * @param int &$line_no Current line number + * @param int $end Optional end line, when we want to chop more + * than one line. + * + * @return array The chopped lines + */ + function _getLines(&$text_lines, &$line_no, $end = false) + { + if (!empty($end)) { + $lines = array(); + // We can shift even more + while ($line_no <= $end) { + array_push($lines, array_shift($text_lines)); + $line_no++; + } + } else { + $lines = array(array_shift($text_lines)); + $line_no++; + } + + return $lines; + } + +} diff --git a/Diff/Diff/Engine/string.php b/Diff/Diff/Engine/string.php new file mode 100644 index 0000000..9352e60 --- /dev/null +++ b/Diff/Diff/Engine/string.php @@ -0,0 +1,250 @@ + + * $patch = file_get_contents('example.patch'); + * $diff = new Text_Diff('string', array($patch)); + * $renderer = new Text_Diff_Renderer_inline(); + * echo $renderer->render($diff); + * + * + * $Horde: framework/Text_Diff/Diff/Engine/string.php,v 1.5.2.7 2009/07/24 13:04:43 jan Exp $ + * + * Copyright 2005 �rjan Persson + * Copyright 2005-2009 The Horde Project (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (LGPL). If you did + * not receive this file, see http://opensource.org/licenses/lgpl-license.php. + * + * @author �rjan Persson + * @package Text_Diff + * @since 0.2.0 + */ +class Text_Diff_Engine_string { + + /** + * Parses a unified or context diff. + * + * First param contains the whole diff and the second can be used to force + * a specific diff type. If the second parameter is 'autodetect', the + * diff will be examined to find out which type of diff this is. + * + * @param string $diff The diff content. + * @param string $mode The diff mode of the content in $diff. One of + * 'context', 'unified', or 'autodetect'. + * + * @return array List of all diff operations. + */ + function diff($diff, $mode = 'autodetect') + { + // Detect line breaks. + $lnbr = "\n"; + if (strpos($diff, "\r\n") !== false) { + $lnbr = "\r\n"; + } elseif (strpos($diff, "\r") !== false) { + $lnbr = "\r"; + } + + // Make sure we have a line break at the EOF. + if (substr($diff, -strlen($lnbr)) != $lnbr) { + $diff .= $lnbr; + } + + if ($mode != 'autodetect' && $mode != 'context' && $mode != 'unified') { + return PEAR::raiseError('Type of diff is unsupported'); + } + + if ($mode == 'autodetect') { + $context = strpos($diff, '***'); + $unified = strpos($diff, '---'); + if ($context === $unified) { + return PEAR::raiseError('Type of diff could not be detected'); + } elseif ($context === false || $unified === false) { + $mode = $context !== false ? 'context' : 'unified'; + } else { + $mode = $context < $unified ? 'context' : 'unified'; + } + } + + // Split by new line and remove the diff header, if there is one. + $diff = explode($lnbr, $diff); + if (($mode == 'context' && strpos($diff[0], '***') === 0) || + ($mode == 'unified' && strpos($diff[0], '---') === 0)) { + array_shift($diff); + array_shift($diff); + } + + if ($mode == 'context') { + return $this->parseContextDiff($diff); + } else { + return $this->parseUnifiedDiff($diff); + } + } + + /** + * Parses an array containing the unified diff. + * + * @param array $diff Array of lines. + * + * @return array List of all diff operations. + */ + function parseUnifiedDiff($diff) + { + $edits = array(); + $end = count($diff) - 1; + for ($i = 0; $i < $end;) { + $diff1 = array(); + switch (substr($diff[$i], 0, 1)) { + case ' ': + do { + $diff1[] = substr($diff[$i], 1); + } while (++$i < $end && substr($diff[$i], 0, 1) == ' '); + $edits[] = new Text_Diff_Op_copy($diff1); + break; + + case '+': + // get all new lines + do { + $diff1[] = substr($diff[$i], 1); + } while (++$i < $end && substr($diff[$i], 0, 1) == '+'); + $edits[] = new Text_Diff_Op_add($diff1); + break; + + case '-': + // get changed or removed lines + $diff2 = array(); + do { + $diff1[] = substr($diff[$i], 1); + } while (++$i < $end && substr($diff[$i], 0, 1) == '-'); + + while ($i < $end && substr($diff[$i], 0, 1) == '+') { + $diff2[] = substr($diff[$i++], 1); + } + if (count($diff2) == 0) { + $edits[] = new Text_Diff_Op_delete($diff1); + } else { + $edits[] = new Text_Diff_Op_change($diff1, $diff2); + } + break; + + default: + $i++; + break; + } + } + + return $edits; + } + + /** + * Parses an array containing the context diff. + * + * @param array $diff Array of lines. + * + * @return array List of all diff operations. + */ + function parseContextDiff(&$diff) + { + $edits = array(); + $i = $max_i = $j = $max_j = 0; + $end = count($diff) - 1; + while ($i < $end && $j < $end) { + while ($i >= $max_i && $j >= $max_j) { + // Find the boundaries of the diff output of the two files + for ($i = $j; + $i < $end && substr($diff[$i], 0, 3) == '***'; + $i++); + for ($max_i = $i; + $max_i < $end && substr($diff[$max_i], 0, 3) != '---'; + $max_i++); + for ($j = $max_i; + $j < $end && substr($diff[$j], 0, 3) == '---'; + $j++); + for ($max_j = $j; + $max_j < $end && substr($diff[$max_j], 0, 3) != '***'; + $max_j++); + } + + // find what hasn't been changed + $array = array(); + while ($i < $max_i && + $j < $max_j && + strcmp($diff[$i], $diff[$j]) == 0) { + $array[] = substr($diff[$i], 2); + $i++; + $j++; + } + + while ($i < $max_i && ($max_j-$j) <= 1) { + if ($diff[$i] != '' && substr($diff[$i], 0, 1) != ' ') { + break; + } + $array[] = substr($diff[$i++], 2); + } + + while ($j < $max_j && ($max_i-$i) <= 1) { + if ($diff[$j] != '' && substr($diff[$j], 0, 1) != ' ') { + break; + } + $array[] = substr($diff[$j++], 2); + } + if (count($array) > 0) { + $edits[] = new Text_Diff_Op_copy($array); + } + + if ($i < $max_i) { + $diff1 = array(); + switch (substr($diff[$i], 0, 1)) { + case '!': + $diff2 = array(); + do { + $diff1[] = substr($diff[$i], 2); + if ($j < $max_j && substr($diff[$j], 0, 1) == '!') { + $diff2[] = substr($diff[$j++], 2); + } + } while (++$i < $max_i && substr($diff[$i], 0, 1) == '!'); + $edits[] = new Text_Diff_Op_change($diff1, $diff2); + break; + + case '+': + do { + $diff1[] = substr($diff[$i], 2); + } while (++$i < $max_i && substr($diff[$i], 0, 1) == '+'); + $edits[] = new Text_Diff_Op_add($diff1); + break; + + case '-': + do { + $diff1[] = substr($diff[$i], 2); + } while (++$i < $max_i && substr($diff[$i], 0, 1) == '-'); + $edits[] = new Text_Diff_Op_delete($diff1); + break; + } + } + + if ($j < $max_j) { + $diff2 = array(); + switch (substr($diff[$j], 0, 1)) { + case '+': + do { + $diff2[] = substr($diff[$j++], 2); + } while ($j < $max_j && substr($diff[$j], 0, 1) == '+'); + $edits[] = new Text_Diff_Op_add($diff2); + break; + + case '-': + do { + $diff2[] = substr($diff[$j++], 2); + } while ($j < $max_j && substr($diff[$j], 0, 1) == '-'); + $edits[] = new Text_Diff_Op_delete($diff2); + break; + } + } + } + + return $edits; + } + +} diff --git a/Diff/Diff/Engine/xdiff.php b/Diff/Diff/Engine/xdiff.php new file mode 100644 index 0000000..241d2e5 --- /dev/null +++ b/Diff/Diff/Engine/xdiff.php @@ -0,0 +1,66 @@ + + * @package Text_Diff + */ +class Text_Diff_Engine_xdiff { + + /** + */ + function diff($from_lines, $to_lines) + { + array_walk($from_lines, array('Text_Diff', 'trimNewlines')); + array_walk($to_lines, array('Text_Diff', 'trimNewlines')); + + /* Convert the two input arrays into strings for xdiff processing. */ + $from_string = implode("\n", $from_lines); + $to_string = implode("\n", $to_lines); + + /* Diff the two strings and convert the result to an array. */ + $diff = xdiff_string_diff($from_string, $to_string, count($to_lines)); + $diff = explode("\n", $diff); + + /* Walk through the diff one line at a time. We build the $edits + * array of diff operations by reading the first character of the + * xdiff output (which is in the "unified diff" format). + * + * Note that we don't have enough information to detect "changed" + * lines using this approach, so we can't add Text_Diff_Op_changed + * instances to the $edits array. The result is still perfectly + * valid, albeit a little less descriptive and efficient. */ + $edits = array(); + foreach ($diff as $line) { + if (!strlen($line)) { + continue; + } + switch ($line[0]) { + case ' ': + $edits[] = &new Text_Diff_Op_copy(array(substr($line, 1))); + break; + + case '+': + $edits[] = &new Text_Diff_Op_add(array(substr($line, 1))); + break; + + case '-': + $edits[] = &new Text_Diff_Op_delete(array(substr($line, 1))); + break; + } + } + + return $edits; + } + +} diff --git a/Diff/Diff/Mapped.php b/Diff/Diff/Mapped.php new file mode 100644 index 0000000..dc46e5e --- /dev/null +++ b/Diff/Diff/Mapped.php @@ -0,0 +1,55 @@ + + */ +class Text_Diff_Mapped extends Text_Diff { + + /** + * Computes a diff between sequences of strings. + * + * This can be used to compute things like case-insensitve diffs, or diffs + * which ignore changes in white-space. + * + * @param array $from_lines An array of strings. + * @param array $to_lines An array of strings. + * @param array $mapped_from_lines This array should have the same size + * number of elements as $from_lines. The + * elements in $mapped_from_lines and + * $mapped_to_lines are what is actually + * compared when computing the diff. + * @param array $mapped_to_lines This array should have the same number + * of elements as $to_lines. + */ + function Text_Diff_Mapped($from_lines, $to_lines, + $mapped_from_lines, $mapped_to_lines) + { + assert(count($from_lines) == count($mapped_from_lines)); + assert(count($to_lines) == count($mapped_to_lines)); + + parent::Text_Diff($mapped_from_lines, $mapped_to_lines); + + $xi = $yi = 0; + for ($i = 0; $i < count($this->_edits); $i++) { + $orig = &$this->_edits[$i]->orig; + if (is_array($orig)) { + $orig = array_slice($from_lines, $xi, count($orig)); + $xi += count($orig); + } + + $final = &$this->_edits[$i]->final; + if (is_array($final)) { + $final = array_slice($to_lines, $yi, count($final)); + $yi += count($final); + } + } + } + +} diff --git a/Diff/Diff/Renderer.php b/Diff/Diff/Renderer.php new file mode 100644 index 0000000..3a51650 --- /dev/null +++ b/Diff/Diff/Renderer.php @@ -0,0 +1,237 @@ + $value) { + $v = '_' . $param; + if (isset($this->$v)) { + $this->$v = $value; + } + } + } + + /** + * Get any renderer parameters. + * + * @return array All parameters of this renderer object. + */ + function getParams() + { + $params = array(); + foreach (get_object_vars($this) as $k => $v) { + if ($k[0] == '_') { + $params[substr($k, 1)] = $v; + } + } + + return $params; + } + + /** + * Renders a diff. + * + * @param Text_Diff $diff A Text_Diff object. + * + * @return string The formatted output. + */ + function render($diff) + { + $xi = $yi = 1; + $block = false; + $context = array(); + + $nlead = $this->_leading_context_lines; + $ntrail = $this->_trailing_context_lines; + + $output = $this->_startDiff(); + + $diffs = $diff->getDiff(); + foreach ($diffs as $i => $edit) { + /* If these are unchanged (copied) lines, and we want to keep + * leading or trailing context lines, extract them from the copy + * block. */ + if (is_a($edit, 'Text_Diff_Op_copy')) { + /* Do we have any diff blocks yet? */ + if (is_array($block)) { + /* How many lines to keep as context from the copy + * block. */ + $keep = $i == count($diffs) - 1 ? $ntrail : $nlead + $ntrail; + if (count($edit->orig) <= $keep) { + /* We have less lines in the block than we want for + * context => keep the whole block. */ + $block[] = $edit; + } else { + if ($ntrail) { + /* Create a new block with as many lines as we need + * for the trailing context. */ + $context = array_slice($edit->orig, 0, $ntrail); + $block[] = new Text_Diff_Op_copy($context); + } + /* @todo */ + $output .= $this->_block($x0, $ntrail + $xi - $x0, + $y0, $ntrail + $yi - $y0, + $block); + $block = false; + } + } + /* Keep the copy block as the context for the next block. */ + $context = $edit->orig; + } else { + /* Don't we have any diff blocks yet? */ + if (!is_array($block)) { + /* Extract context lines from the preceding copy block. */ + $context = array_slice($context, count($context) - $nlead); + $x0 = $xi - count($context); + $y0 = $yi - count($context); + $block = array(); + if ($context) { + $block[] = new Text_Diff_Op_copy($context); + } + } + $block[] = $edit; + } + + if ($edit->orig) { + $xi += count($edit->orig); + } + if ($edit->final) { + $yi += count($edit->final); + } + } + + if (is_array($block)) { + $output .= $this->_block($x0, $xi - $x0, + $y0, $yi - $y0, + $block); + } + + return $output . $this->_endDiff(); + } + + function _block($xbeg, $xlen, $ybeg, $ylen, &$edits) + { + $output = $this->_startBlock($this->_blockHeader($xbeg, $xlen, $ybeg, $ylen)); + + foreach ($edits as $edit) { + switch (strtolower(get_class($edit))) { + case 'text_diff_op_copy': + $output .= $this->_context($edit->orig); + break; + + case 'text_diff_op_add': + $output .= $this->_added($edit->final); + break; + + case 'text_diff_op_delete': + $output .= $this->_deleted($edit->orig); + break; + + case 'text_diff_op_change': + $output .= $this->_changed($edit->orig, $edit->final); + break; + } + } + + return $output . $this->_endBlock(); + } + + function _startDiff() + { + return ''; + } + + function _endDiff() + { + return ''; + } + + function _blockHeader($xbeg, $xlen, $ybeg, $ylen) + { + if ($xlen > 1) { + $xbeg .= ',' . ($xbeg + $xlen - 1); + } + if ($ylen > 1) { + $ybeg .= ',' . ($ybeg + $ylen - 1); + } + + // this matches the GNU Diff behaviour + if ($xlen && !$ylen) { + $ybeg--; + } elseif (!$xlen) { + $xbeg--; + } + + return $xbeg . ($xlen ? ($ylen ? 'c' : 'd') : 'a') . $ybeg; + } + + function _startBlock($header) + { + return $header . "\n"; + } + + function _endBlock() + { + return ''; + } + + function _lines($lines, $prefix = ' ') + { + return $prefix . implode("\n$prefix", $lines) . "\n"; + } + + function _context($lines) + { + return $this->_lines($lines, ' '); + } + + function _added($lines) + { + return $this->_lines($lines, '> '); + } + + function _deleted($lines) + { + return $this->_lines($lines, '< '); + } + + function _changed($orig, $final) + { + return $this->_deleted($orig) . "---\n" . $this->_added($final); + } + +} diff --git a/Diff/Diff/Renderer/context.php b/Diff/Diff/Renderer/context.php new file mode 100644 index 0000000..af53801 --- /dev/null +++ b/Diff/Diff/Renderer/context.php @@ -0,0 +1,77 @@ +_second_block = "--- $ybeg ----\n"; + return "***************\n*** $xbeg ****"; + } + + function _endBlock() + { + return $this->_second_block; + } + + function _context($lines) + { + $this->_second_block .= $this->_lines($lines, ' '); + return $this->_lines($lines, ' '); + } + + function _added($lines) + { + $this->_second_block .= $this->_lines($lines, '+ '); + return ''; + } + + function _deleted($lines) + { + return $this->_lines($lines, '- '); + } + + function _changed($orig, $final) + { + $this->_second_block .= $this->_lines($final, '! '); + return $this->_lines($orig, '! '); + } + +} diff --git a/Diff/Diff/Renderer/inline.php b/Diff/Diff/Renderer/inline.php new file mode 100644 index 0000000..5dd20d2 --- /dev/null +++ b/Diff/Diff/Renderer/inline.php @@ -0,0 +1,172 @@ +'; + + /** + * Suffix for inserted text. + */ + var $_ins_suffix = ''; + + /** + * Prefix for deleted text. + */ + var $_del_prefix = ''; + + /** + * Suffix for deleted text. + */ + var $_del_suffix = ''; + + /** + * Header for each change block. + */ + var $_block_header = ''; + + /** + * What are we currently splitting on? Used to recurse to show word-level + * changes. + */ + var $_split_level = 'lines'; + + function _blockHeader($xbeg, $xlen, $ybeg, $ylen) + { + return $this->_block_header; + } + + function _startBlock($header) + { + return $header; + } + + function _lines($lines, $prefix = ' ', $encode = true) + { + if ($encode) { + array_walk($lines, array(&$this, '_encode')); + } + + if ($this->_split_level == 'words') { + return implode('', $lines); + } else { + return implode("\n", $lines) . "\n"; + } + } + + function _added($lines) + { + array_walk($lines, array(&$this, '_encode')); + $lines[0] = $this->_ins_prefix . $lines[0]; + $lines[count($lines) - 1] .= $this->_ins_suffix; + return $this->_lines($lines, ' ', false); + } + + function _deleted($lines, $words = false) + { + array_walk($lines, array(&$this, '_encode')); + $lines[0] = $this->_del_prefix . $lines[0]; + $lines[count($lines) - 1] .= $this->_del_suffix; + return $this->_lines($lines, ' ', false); + } + + function _changed($orig, $final) + { + /* If we've already split on words, don't try to do so again - just + * display. */ + if ($this->_split_level == 'words') { + $prefix = ''; + while ($orig[0] !== false && $final[0] !== false && + substr($orig[0], 0, 1) == ' ' && + substr($final[0], 0, 1) == ' ') { + $prefix .= substr($orig[0], 0, 1); + $orig[0] = substr($orig[0], 1); + $final[0] = substr($final[0], 1); + } + return $prefix . $this->_deleted($orig) . $this->_added($final); + } + + $text1 = implode("\n", $orig); + $text2 = implode("\n", $final); + + /* Non-printing newline marker. */ + $nl = "\0"; + + /* We want to split on word boundaries, but we need to + * preserve whitespace as well. Therefore we split on words, + * but include all blocks of whitespace in the wordlist. */ + $diff = new Text_Diff('native', + array($this->_splitOnWords($text1, $nl), + $this->_splitOnWords($text2, $nl))); + + /* Get the diff in inline format. */ + $renderer = new Text_Diff_Renderer_inline + (array_merge($this->getParams(), + array('split_level' => 'words'))); + + /* Run the diff and get the output. */ + return str_replace($nl, "\n", $renderer->render($diff)) . "\n"; + } + + function _splitOnWords($string, $newlineEscape = "\n") + { + // Ignore \0; otherwise the while loop will never finish. + $string = str_replace("\0", '', $string); + + $words = array(); + $length = strlen($string); + $pos = 0; + + while ($pos < $length) { + // Eat a word with any preceding whitespace. + $spaces = strspn(substr($string, $pos), " \n"); + $nextpos = strcspn(substr($string, $pos + $spaces), " \n"); + $words[] = str_replace("\n", $newlineEscape, substr($string, $pos, $spaces + $nextpos)); + $pos += $spaces + $nextpos; + } + + return $words; + } + + function _encode(&$string) + { + $string = htmlspecialchars($string); + } + +} diff --git a/Diff/Diff/Renderer/unified.php b/Diff/Diff/Renderer/unified.php new file mode 100644 index 0000000..f990f72 --- /dev/null +++ b/Diff/Diff/Renderer/unified.php @@ -0,0 +1,67 @@ +_lines($lines, ' '); + } + + function _added($lines) + { + return $this->_lines($lines, '+'); + } + + function _deleted($lines) + { + return $this->_lines($lines, '-'); + } + + function _changed($orig, $final) + { + return $this->_deleted($orig) . $this->_added($final); + } + +} diff --git a/Diff/Diff/ThreeWay.php b/Diff/Diff/ThreeWay.php new file mode 100644 index 0000000..5b0357c --- /dev/null +++ b/Diff/Diff/ThreeWay.php @@ -0,0 +1,276 @@ + + */ +class Text_Diff_ThreeWay extends Text_Diff { + + /** + * Conflict counter. + * + * @var integer + */ + var $_conflictingBlocks = 0; + + /** + * Computes diff between 3 sequences of strings. + * + * @param array $orig The original lines to use. + * @param array $final1 The first version to compare to. + * @param array $final2 The second version to compare to. + */ + function Text_Diff_ThreeWay($orig, $final1, $final2) + { + if (extension_loaded('xdiff')) { + $engine = new Text_Diff_Engine_xdiff(); + } else { + $engine = new Text_Diff_Engine_native(); + } + + $this->_edits = $this->_diff3($engine->diff($orig, $final1), + $engine->diff($orig, $final2)); + } + + /** + */ + function mergedOutput($label1 = false, $label2 = false) + { + $lines = array(); + foreach ($this->_edits as $edit) { + if ($edit->isConflict()) { + /* FIXME: this should probably be moved somewhere else. */ + $lines = array_merge($lines, + array('<<<<<<<' . ($label1 ? ' ' . $label1 : '')), + $edit->final1, + array("======="), + $edit->final2, + array('>>>>>>>' . ($label2 ? ' ' . $label2 : ''))); + $this->_conflictingBlocks++; + } else { + $lines = array_merge($lines, $edit->merged()); + } + } + + return $lines; + } + + /** + * @access private + */ + function _diff3($edits1, $edits2) + { + $edits = array(); + $bb = new Text_Diff_ThreeWay_BlockBuilder(); + + $e1 = current($edits1); + $e2 = current($edits2); + while ($e1 || $e2) { + if ($e1 && $e2 && is_a($e1, 'Text_Diff_Op_copy') && is_a($e2, 'Text_Diff_Op_copy')) { + /* We have copy blocks from both diffs. This is the (only) + * time we want to emit a diff3 copy block. Flush current + * diff3 diff block, if any. */ + if ($edit = $bb->finish()) { + $edits[] = $edit; + } + + $ncopy = min($e1->norig(), $e2->norig()); + assert($ncopy > 0); + $edits[] = new Text_Diff_ThreeWay_Op_copy(array_slice($e1->orig, 0, $ncopy)); + + if ($e1->norig() > $ncopy) { + array_splice($e1->orig, 0, $ncopy); + array_splice($e1->final, 0, $ncopy); + } else { + $e1 = next($edits1); + } + + if ($e2->norig() > $ncopy) { + array_splice($e2->orig, 0, $ncopy); + array_splice($e2->final, 0, $ncopy); + } else { + $e2 = next($edits2); + } + } else { + if ($e1 && $e2) { + if ($e1->orig && $e2->orig) { + $norig = min($e1->norig(), $e2->norig()); + $orig = array_splice($e1->orig, 0, $norig); + array_splice($e2->orig, 0, $norig); + $bb->input($orig); + } + + if (is_a($e1, 'Text_Diff_Op_copy')) { + $bb->out1(array_splice($e1->final, 0, $norig)); + } + + if (is_a($e2, 'Text_Diff_Op_copy')) { + $bb->out2(array_splice($e2->final, 0, $norig)); + } + } + + if ($e1 && ! $e1->orig) { + $bb->out1($e1->final); + $e1 = next($edits1); + } + if ($e2 && ! $e2->orig) { + $bb->out2($e2->final); + $e2 = next($edits2); + } + } + } + + if ($edit = $bb->finish()) { + $edits[] = $edit; + } + + return $edits; + } + +} + +/** + * @package Text_Diff + * @author Geoffrey T. Dairiki + * + * @access private + */ +class Text_Diff_ThreeWay_Op { + + function Text_Diff_ThreeWay_Op($orig = false, $final1 = false, $final2 = false) + { + $this->orig = $orig ? $orig : array(); + $this->final1 = $final1 ? $final1 : array(); + $this->final2 = $final2 ? $final2 : array(); + } + + function merged() + { + if (!isset($this->_merged)) { + if ($this->final1 === $this->final2) { + $this->_merged = &$this->final1; + } elseif ($this->final1 === $this->orig) { + $this->_merged = &$this->final2; + } elseif ($this->final2 === $this->orig) { + $this->_merged = &$this->final1; + } else { + $this->_merged = false; + } + } + + return $this->_merged; + } + + function isConflict() + { + return $this->merged() === false; + } + +} + +/** + * @package Text_Diff + * @author Geoffrey T. Dairiki + * + * @access private + */ +class Text_Diff_ThreeWay_Op_copy extends Text_Diff_ThreeWay_Op { + + function Text_Diff_ThreeWay_Op_Copy($lines = false) + { + $this->orig = $lines ? $lines : array(); + $this->final1 = &$this->orig; + $this->final2 = &$this->orig; + } + + function merged() + { + return $this->orig; + } + + function isConflict() + { + return false; + } + +} + +/** + * @package Text_Diff + * @author Geoffrey T. Dairiki + * + * @access private + */ +class Text_Diff_ThreeWay_BlockBuilder { + + function Text_Diff_ThreeWay_BlockBuilder() + { + $this->_init(); + } + + function input($lines) + { + if ($lines) { + $this->_append($this->orig, $lines); + } + } + + function out1($lines) + { + if ($lines) { + $this->_append($this->final1, $lines); + } + } + + function out2($lines) + { + if ($lines) { + $this->_append($this->final2, $lines); + } + } + + function isEmpty() + { + return !$this->orig && !$this->final1 && !$this->final2; + } + + function finish() + { + if ($this->isEmpty()) { + return false; + } else { + $edit = new Text_Diff_ThreeWay_Op($this->orig, $this->final1, $this->final2); + $this->_init(); + return $edit; + } + } + + function _init() + { + $this->orig = $this->final1 = $this->final2 = array(); + } + + function _append(&$array, $lines) + { + array_splice($array, sizeof($array), 0, $lines); + } + +} diff --git a/Diff/Diff3.php b/Diff/Diff3.php new file mode 100644 index 0000000..e9aea9f --- /dev/null +++ b/Diff/Diff3.php @@ -0,0 +1,276 @@ + + */ +class Text_Diff3 extends Text_Diff { + + /** + * Conflict counter. + * + * @var integer + */ + var $_conflictingBlocks = 0; + + /** + * Computes diff between 3 sequences of strings. + * + * @param array $orig The original lines to use. + * @param array $final1 The first version to compare to. + * @param array $final2 The second version to compare to. + */ + function Text_Diff3($orig, $final1, $final2) + { + if (extension_loaded('xdiff')) { + $engine = new Text_Diff_Engine_xdiff(); + } else { + $engine = new Text_Diff_Engine_native(); + } + + $this->_edits = $this->_diff3($engine->diff($orig, $final1), + $engine->diff($orig, $final2)); + } + + /** + */ + function mergedOutput($label1 = false, $label2 = false) + { + $lines = array(); + foreach ($this->_edits as $edit) { + if ($edit->isConflict()) { + /* FIXME: this should probably be moved somewhere else. */ + $lines = array_merge($lines, + array('<<<<<<<' . ($label1 ? ' ' . $label1 : '')), + $edit->final1, + array("======="), + $edit->final2, + array('>>>>>>>' . ($label2 ? ' ' . $label2 : ''))); + $this->_conflictingBlocks++; + } else { + $lines = array_merge($lines, $edit->merged()); + } + } + + return $lines; + } + + /** + * @access private + */ + function _diff3($edits1, $edits2) + { + $edits = array(); + $bb = new Text_Diff3_BlockBuilder(); + + $e1 = current($edits1); + $e2 = current($edits2); + while ($e1 || $e2) { + if ($e1 && $e2 && is_a($e1, 'Text_Diff_Op_copy') && is_a($e2, 'Text_Diff_Op_copy')) { + /* We have copy blocks from both diffs. This is the (only) + * time we want to emit a diff3 copy block. Flush current + * diff3 diff block, if any. */ + if ($edit = $bb->finish()) { + $edits[] = $edit; + } + + $ncopy = min($e1->norig(), $e2->norig()); + assert($ncopy > 0); + $edits[] = new Text_Diff3_Op_copy(array_slice($e1->orig, 0, $ncopy)); + + if ($e1->norig() > $ncopy) { + array_splice($e1->orig, 0, $ncopy); + array_splice($e1->final, 0, $ncopy); + } else { + $e1 = next($edits1); + } + + if ($e2->norig() > $ncopy) { + array_splice($e2->orig, 0, $ncopy); + array_splice($e2->final, 0, $ncopy); + } else { + $e2 = next($edits2); + } + } else { + if ($e1 && $e2) { + if ($e1->orig && $e2->orig) { + $norig = min($e1->norig(), $e2->norig()); + $orig = array_splice($e1->orig, 0, $norig); + array_splice($e2->orig, 0, $norig); + $bb->input($orig); + } + + if (is_a($e1, 'Text_Diff_Op_copy')) { + $bb->out1(array_splice($e1->final, 0, $norig)); + } + + if (is_a($e2, 'Text_Diff_Op_copy')) { + $bb->out2(array_splice($e2->final, 0, $norig)); + } + } + + if ($e1 && ! $e1->orig) { + $bb->out1($e1->final); + $e1 = next($edits1); + } + if ($e2 && ! $e2->orig) { + $bb->out2($e2->final); + $e2 = next($edits2); + } + } + } + + if ($edit = $bb->finish()) { + $edits[] = $edit; + } + + return $edits; + } + +} + +/** + * @package Text_Diff + * @author Geoffrey T. Dairiki + * + * @access private + */ +class Text_Diff3_Op { + + function Text_Diff3_Op($orig = false, $final1 = false, $final2 = false) + { + $this->orig = $orig ? $orig : array(); + $this->final1 = $final1 ? $final1 : array(); + $this->final2 = $final2 ? $final2 : array(); + } + + function merged() + { + if (!isset($this->_merged)) { + if ($this->final1 === $this->final2) { + $this->_merged = &$this->final1; + } elseif ($this->final1 === $this->orig) { + $this->_merged = &$this->final2; + } elseif ($this->final2 === $this->orig) { + $this->_merged = &$this->final1; + } else { + $this->_merged = false; + } + } + + return $this->_merged; + } + + function isConflict() + { + return $this->merged() === false; + } + +} + +/** + * @package Text_Diff + * @author Geoffrey T. Dairiki + * + * @access private + */ +class Text_Diff3_Op_copy extends Text_Diff3_Op { + + function Text_Diff3_Op_Copy($lines = false) + { + $this->orig = $lines ? $lines : array(); + $this->final1 = &$this->orig; + $this->final2 = &$this->orig; + } + + function merged() + { + return $this->orig; + } + + function isConflict() + { + return false; + } + +} + +/** + * @package Text_Diff + * @author Geoffrey T. Dairiki + * + * @access private + */ +class Text_Diff3_BlockBuilder { + + function Text_Diff3_BlockBuilder() + { + $this->_init(); + } + + function input($lines) + { + if ($lines) { + $this->_append($this->orig, $lines); + } + } + + function out1($lines) + { + if ($lines) { + $this->_append($this->final1, $lines); + } + } + + function out2($lines) + { + if ($lines) { + $this->_append($this->final2, $lines); + } + } + + function isEmpty() + { + return !$this->orig && !$this->final1 && !$this->final2; + } + + function finish() + { + if ($this->isEmpty()) { + return false; + } else { + $edit = new Text_Diff3_Op($this->orig, $this->final1, $this->final2); + $this->_init(); + return $edit; + } + } + + function _init() + { + $this->orig = $this->final1 = $this->final2 = array(); + } + + function _append(&$array, $lines) + { + array_splice($array, sizeof($array), 0, $lines); + } + +} diff --git a/Diff/docs/examples/1.txt b/Diff/docs/examples/1.txt new file mode 100644 index 0000000..976c447 --- /dev/null +++ b/Diff/docs/examples/1.txt @@ -0,0 +1,3 @@ +This line is the same. +This line is different in 1.txt +This line is the same. diff --git a/Diff/docs/examples/2.txt b/Diff/docs/examples/2.txt new file mode 100644 index 0000000..6fa8051 --- /dev/null +++ b/Diff/docs/examples/2.txt @@ -0,0 +1,3 @@ +This line is the same. +This line is different in 2.txt +This line is the same. diff --git a/Diff/docs/examples/diff.php b/Diff/docs/examples/diff.php new file mode 100644 index 0000000..66914c2 --- /dev/null +++ b/Diff/docs/examples/diff.php @@ -0,0 +1,39 @@ +#!/usr/bin/php + \n\n"; + exit; +} + +/* Make sure both files exist. */ +if (!is_readable($argv[1])) { + echo "$argv[1] not found or not readable.\n\n"; +} +if (!is_readable($argv[2])) { + echo "$argv[2] not found or not readable.\n\n"; +} + +/* Load the lines of each file. */ +$lines1 = file($argv[1]); +$lines2 = file($argv[2]); + +/* Create the Diff object. */ +$diff = new Text_Diff('auto', array($lines1, $lines2)); + +/* Output the diff in unified format. */ +$renderer = new Text_Diff_Renderer_unified(); +echo $renderer->render($diff); diff --git a/Diff/tests/1.txt b/Diff/tests/1.txt new file mode 100644 index 0000000..976c447 --- /dev/null +++ b/Diff/tests/1.txt @@ -0,0 +1,3 @@ +This line is the same. +This line is different in 1.txt +This line is the same. diff --git a/Diff/tests/2.txt b/Diff/tests/2.txt new file mode 100644 index 0000000..6fa8051 --- /dev/null +++ b/Diff/tests/2.txt @@ -0,0 +1,3 @@ +This line is the same. +This line is different in 2.txt +This line is the same. diff --git a/Diff/tests/3.txt b/Diff/tests/3.txt new file mode 100644 index 0000000..0c26fe9 --- /dev/null +++ b/Diff/tests/3.txt @@ -0,0 +1,4 @@ +This line is the same. +This line is different in 1.txt +This line is the same. +This line is new in 3.txt diff --git a/Diff/tests/4.txt b/Diff/tests/4.txt new file mode 100644 index 0000000..7cbc69d --- /dev/null +++ b/Diff/tests/4.txt @@ -0,0 +1,3 @@ +This line is the same. +This line is different in 4.txt +This line is the same. diff --git a/Diff/tests/5.txt b/Diff/tests/5.txt new file mode 100644 index 0000000..d48db22 --- /dev/null +++ b/Diff/tests/5.txt @@ -0,0 +1,5 @@ +This is a test. +Adding random text to simulate files. +Various Content. +More Content. +Testing diff and renderer. diff --git a/Diff/tests/6.txt b/Diff/tests/6.txt new file mode 100644 index 0000000..5b421cd --- /dev/null +++ b/Diff/tests/6.txt @@ -0,0 +1,7 @@ +This is a test. +Adding random text to simulate files. +Inserting a line. +Various Content. +Replacing content. +Testing similarities and renderer. +Append content. diff --git a/Diff/tests/context.patch b/Diff/tests/context.patch new file mode 100644 index 0000000..2a4fad9 --- /dev/null +++ b/Diff/tests/context.patch @@ -0,0 +1,11 @@ +*** 1.txt 2005-03-21 13:37:59.000000000 +0100 +--- 2.txt 2005-03-21 13:38:00.000000000 +0100 +*************** +*** 1,3 **** + This line is the same. +! This line is different in 1.txt + This line is the same. +--- 1,3 ---- + This line is the same. +! This line is different in 2.txt + This line is the same. diff --git a/Diff/tests/context.phpt b/Diff/tests/context.phpt new file mode 100644 index 0000000..5891ea4 --- /dev/null +++ b/Diff/tests/context.phpt @@ -0,0 +1,25 @@ +--TEST-- +Text_Diff: Context renderer +--FILE-- +render($diff); +?> +--EXPECT-- +*************** +*** 1,3 **** + This line is the same. +! This line is different in 1.txt + This line is the same. +--- 1,3 ---- + This line is the same. +! This line is different in 2.txt + This line is the same. diff --git a/Diff/tests/context2.phpt b/Diff/tests/context2.phpt new file mode 100644 index 0000000..6d8f248 --- /dev/null +++ b/Diff/tests/context2.phpt @@ -0,0 +1,31 @@ +--TEST-- +Text_Diff: Context renderer 2 +--FILE-- +render($diff); +?> +--EXPECT-- +*************** +*** 1,5 **** + This is a test. + Adding random text to simulate files. + Various Content. +! More Content. +! Testing diff and renderer. +--- 1,7 ---- + This is a test. + Adding random text to simulate files. ++ Inserting a line. + Various Content. +! Replacing content. +! Testing similarities and renderer. +! Append content. diff --git a/Diff/tests/diff.phpt b/Diff/tests/diff.phpt new file mode 100644 index 0000000..add291f --- /dev/null +++ b/Diff/tests/diff.phpt @@ -0,0 +1,62 @@ +--TEST-- +Text_Diff: Basic diff operation +--FILE-- + +--EXPECT-- +text_diff object +( + [_edits] => array + ( + [0] => text_diff_op_copy object + ( + [orig] => array + ( + [0] => this line is the same. + ) + + [final] => array + ( + [0] => this line is the same. + ) + + ) + + [1] => text_diff_op_change object + ( + [orig] => array + ( + [0] => this line is different in 1.txt + ) + + [final] => array + ( + [0] => this line is different in 2.txt + ) + + ) + + [2] => text_diff_op_copy object + ( + [orig] => array + ( + [0] => this line is the same. + ) + + [final] => array + ( + [0] => this line is the same. + ) + + ) + + ) + +) diff --git a/Diff/tests/inline.phpt b/Diff/tests/inline.phpt new file mode 100644 index 0000000..b3d1ba7 --- /dev/null +++ b/Diff/tests/inline.phpt @@ -0,0 +1,19 @@ +--TEST-- +Text_Diff: Inline renderer +--FILE-- +render($diff); +?> +--EXPECT-- +This line is the same. +This line is different in 1.txt2.txt +This line is the same. diff --git a/Diff/tests/inline2.phpt b/Diff/tests/inline2.phpt new file mode 100644 index 0000000..153a39f --- /dev/null +++ b/Diff/tests/inline2.phpt @@ -0,0 +1,37 @@ +--TEST-- +Text_Diff: Inline renderer 2 +--FILE-- +render($diff); +?> +--EXPECT-- +This is a test. +Adding random text to simulate files. +Inserting a line. +Various Content. +More Content.Replacing content. +Testing diffsimilarities and renderer. +Append content. diff --git a/Diff/tests/pear_bug12740.phpt b/Diff/tests/pear_bug12740.phpt new file mode 100644 index 0000000..56b4ced --- /dev/null +++ b/Diff/tests/pear_bug12740.phpt @@ -0,0 +1,30 @@ +--TEST-- +Text_Diff: PEAR Bug #12740 (failed assertion) +--FILE-- +The tax credit amounts to 30% of the cost of the system, with a +maximum of 2,000. This credit is separate from the 500 home improvement +credit. +

Fuel Cells
+
  • Your fuel 123456789
  • +QQ; + +$b = << of gas emissions by 2050 +
  • Raise car fuel economy to 50 mpg by 2017
  • +
  • Increase access to mass transit systems
  • +QQ; + +$diff = new Text_Diff('native', array(explode("\n", $b), explode("\n", $a))); +$renderer = new Text_Diff_Renderer_inline(); +$renderer->render($diff); + +?> +--EXPECT-- diff --git a/Diff/tests/pear_bug4879.phpt b/Diff/tests/pear_bug4879.phpt new file mode 100644 index 0000000..5bb657b --- /dev/null +++ b/Diff/tests/pear_bug4879.phpt @@ -0,0 +1,30 @@ +--TEST-- +Text_Diff: PEAR Bug #4879 (inline renderer hangs on numbers in input string) +--FILE-- +render($diff); +?> +--EXPECT-- +Common text +Bob had 1 apple,10 apples, Alice had 2.1. +Bon appetit! diff --git a/Diff/tests/pear_bug6251.phpt b/Diff/tests/pear_bug6251.phpt new file mode 100644 index 0000000..86af082 --- /dev/null +++ b/Diff/tests/pear_bug6251.phpt @@ -0,0 +1,45 @@ +--TEST-- +Text_Diff: PEAR Bug #6251 (too much trailing context) +--FILE-- + 3, 'trailing_context_lines' => 3)); + +// We need to use var_dump, as the test runner strips trailing empty lines. +var_dump($renderer->render($diff)); +?> +--EXPECT-- +string(54) "@@ -1,5 +1,5 @@ + +-Original Text ++Modified Text + + + +" diff --git a/Diff/tests/pear_bug6428.phpt b/Diff/tests/pear_bug6428.phpt new file mode 100644 index 0000000..9d5b982 --- /dev/null +++ b/Diff/tests/pear_bug6428.phpt @@ -0,0 +1,18 @@ +--TEST-- +Text_Diff: PEAR Bug #6428 (problem with single digits after space) +--FILE-- +render($diff); +?> +--EXPECT-- +Line 1 1 +Another line diff --git a/Diff/tests/string.phpt b/Diff/tests/string.phpt new file mode 100644 index 0000000..9001198 --- /dev/null +++ b/Diff/tests/string.phpt @@ -0,0 +1,145 @@ +--TEST-- +Text_Diff: Text_Diff_Engine_string test. +--FILE-- +getDiff(), 'PEAR_Error')); +echo "\n"; +$diff_u2 = new Text_Diff('string', array($unified2, 'unified')); +echo strtolower(print_r($diff_u2, true)); + +$context = file_get_contents(dirname(__FILE__) . '/context.patch'); +$diff_c = new Text_Diff('string', array($context)); +echo strtolower(print_r($diff_c, true)); + +?> +--EXPECT-- +text_diff object +( + [_edits] => array + ( + [0] => text_diff_op_copy object + ( + [orig] => array + ( + [0] => this line is the same. + ) + + [final] => array + ( + [0] => this line is the same. + ) + + ) + + [1] => text_diff_op_change object + ( + [orig] => array + ( + [0] => this line is different in 1.txt + ) + + [final] => array + ( + [0] => this line is different in 2.txt + ) + + ) + + [2] => text_diff_op_copy object + ( + [orig] => array + ( + [0] => this line is the same. + ) + + [final] => array + ( + [0] => this line is the same. + ) + + ) + + ) + +) +true +text_diff object +( + [_edits] => array + ( + [0] => text_diff_op_change object + ( + [orig] => array + ( + [0] => for the first time in u.s. history number of private contractors and troops are equal + ) + + [final] => array + ( + [0] => number of private contractors and troops are equal for first time in u.s. history + ) + + ) + + ) + +) +text_diff object +( + [_edits] => array + ( + [0] => text_diff_op_copy object + ( + [orig] => array + ( + [0] => this line is the same. + ) + + [final] => array + ( + [0] => this line is the same. + ) + + ) + + [1] => text_diff_op_change object + ( + [orig] => array + ( + [0] => this line is different in 1.txt + ) + + [final] => array + ( + [0] => this line is different in 2.txt + ) + + ) + + [2] => text_diff_op_copy object + ( + [orig] => array + ( + [0] => this line is the same. + ) + + [final] => array + ( + [0] => this line is the same. + ) + + ) + + ) + +) diff --git a/Diff/tests/unified.patch b/Diff/tests/unified.patch new file mode 100644 index 0000000..b2b3f25 --- /dev/null +++ b/Diff/tests/unified.patch @@ -0,0 +1,7 @@ +--- 1.txt 2005-03-21 13:37:59.000000000 +0100 ++++ 2.txt 2005-03-21 13:38:00.000000000 +0100 +@@ -1,3 +1,3 @@ + This line is the same. +-This line is different in 1.txt ++This line is different in 2.txt + This line is the same. diff --git a/Diff/tests/unified.phpt b/Diff/tests/unified.phpt new file mode 100644 index 0000000..4c279dd --- /dev/null +++ b/Diff/tests/unified.phpt @@ -0,0 +1,21 @@ +--TEST-- +Text_Diff: Unified renderer +--FILE-- +render($diff); +?> +--EXPECT-- +@@ -1,3 +1,3 @@ + This line is the same. +-This line is different in 1.txt ++This line is different in 2.txt + This line is the same. diff --git a/Diff/tests/unified2.phpt b/Diff/tests/unified2.phpt new file mode 100644 index 0000000..303b329 --- /dev/null +++ b/Diff/tests/unified2.phpt @@ -0,0 +1,26 @@ +--TEST-- +Text_Diff: Unified renderer 2 +--FILE-- +render($diff); +?> +--EXPECT-- +@@ -1,5 +1,7 @@ + This is a test. + Adding random text to simulate files. ++Inserting a line. + Various Content. +-More Content. +-Testing diff and renderer. ++Replacing content. ++Testing similarities and renderer. ++Append content. diff --git a/Diff/tests/xdiff.phpt b/Diff/tests/xdiff.phpt new file mode 100644 index 0000000..0be5379 --- /dev/null +++ b/Diff/tests/xdiff.phpt @@ -0,0 +1,24 @@ +--TEST-- +Text_Diff: Text_Diff_Engine_xdiff test. +--SKIPIF-- + +--FILE-- +render($diff); + +?> +--EXPECT-- +@@ -1,3 +1,3 @@ + This line is the same. +-This line is different in 1.txt ++This line is different in 2.txt + This line is the same. diff --git a/c/.idea/.name b/c/.idea/.name new file mode 100644 index 0000000..3410062 --- /dev/null +++ b/c/.idea/.name @@ -0,0 +1 @@ +c \ No newline at end of file diff --git a/c/.idea/c.iml b/c/.idea/c.iml new file mode 100644 index 0000000..6b8184f --- /dev/null +++ b/c/.idea/c.iml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/c/.idea/encodings.xml b/c/.idea/encodings.xml new file mode 100644 index 0000000..e206d70 --- /dev/null +++ b/c/.idea/encodings.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/c/.idea/inspectionProfiles/Project_Default.xml b/c/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..07b00cc --- /dev/null +++ b/c/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,219 @@ + + + + \ No newline at end of file diff --git a/c/.idea/inspectionProfiles/profiles_settings.xml b/c/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..3b31283 --- /dev/null +++ b/c/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/c/.idea/misc.xml b/c/.idea/misc.xml new file mode 100644 index 0000000..e399830 --- /dev/null +++ b/c/.idea/misc.xml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + General + + + PHP + + + + + XSLT + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/c/.idea/modules.xml b/c/.idea/modules.xml new file mode 100644 index 0000000..734d0c6 --- /dev/null +++ b/c/.idea/modules.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/c/.idea/scopes/scope_settings.xml b/c/.idea/scopes/scope_settings.xml new file mode 100644 index 0000000..922003b --- /dev/null +++ b/c/.idea/scopes/scope_settings.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/c/.idea/vcs.xml b/c/.idea/vcs.xml new file mode 100644 index 0000000..def6a6a --- /dev/null +++ b/c/.idea/vcs.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/c/.idea/workspace.xml b/c/.idea/workspace.xml new file mode 100644 index 0000000..62fa21f --- /dev/null +++ b/c/.idea/workspace.xml @@ -0,0 +1,347 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1385753937101 + 1385753937101 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/c/a.php b/c/a.php new file mode 100644 index 0000000..451e3ee --- /dev/null +++ b/c/a.php @@ -0,0 +1,32 @@ +[^<]*<\/sc>/ui"; +$regex2 = "/((\n|\A)[^\n]*)[^<]{2,4}<\/sc>([^\n]*)/ui"; + +$ids = $dpdb->SqlValues("SELECT projectid FROM projects WHERE phase = 'PP'"); +$n = 0; +foreach($ids as $id) { + $proj = new DpProject($id); + $text = $proj->RoundText("F2"); +// dump($id); +// preg_match_all($regex1, $text, $matches1); + preg_match_all($regex2, $text, $matches2); +// dump(count($matches)); +// dump(++$n . " $id " . count($matches1[0]) . " " . count($matches2[0])); +// if(count($matches1[0]) > 1000) { + if(count($matches2[0]) > 10) { +// for($i = 0; $i < 100; $i++ ) { + foreach($matches2[0] as $m) { + dump(h($m)); + } + } +} + diff --git a/c/accounts/login.php b/c/accounts/login.php new file mode 100644 index 0000000..512451b --- /dev/null +++ b/c/accounts/login.php @@ -0,0 +1,27 @@ +IsLoggedIn() && $userNM != "" && $userPW != "") { + $User->Logout(); +} + +//if($userNM && $userPW) { +// $User = new DpThisUser($userNM, $userPW); +// if(! $User->IsLoggedIn()) { +// $destination = $forum_login_url; +// } +//} + +divert($destination); diff --git a/c/accounts/signin.php b/c/accounts/signin.php new file mode 100644 index 0000000..e4e744a --- /dev/null +++ b/c/accounts/signin.php @@ -0,0 +1,11 @@ +Make sure your caps lock is not on."); +theme("", "footer"); +?> diff --git a/c/activity_hub.php b/c/activity_hub.php new file mode 100644 index 0000000..b269ac8 --- /dev/null +++ b/c/activity_hub.php @@ -0,0 +1,384 @@ + "/c/js/dp_ajax.js"); +//$opts = array("hdr_include" => "c.php"); +theme($ahtitle, "header", $opts); + +echo "\n"; + + +echo " +
    + $ahtitle +

    + ".link_to_metal_list("Gold", "Recently Published Ebooks")." +

    +
    \n"; + +/* +echo " +
    +
    + Trouble with login? + +
    +
    \n"; +*/ + +show_admin_links(); + +if ( $User->PageCount() <= 300 && $User->InboxCount() > 0 ) { + echo + "
    +
    \n"; + + echo _(" +

    You have received a private message in your Inbox!

    "); + echo _("

    This could be from somebody sending you feedback on some of the + pages you had proofread earlier. We strongly recommend you READ your + messages. In the links at the top of this page, there is one that says + My Inbox. Just click on that to open your Inbox.

    "); + echo _("

    (After a while this explanatory paragraph will not appear when + you have new messages, but the link to your Inbox will always be up + there and when you have new messages that will be shown in the link)

    "); + echo "
    "; +} + + + +if ($User->PageCount() <= 100) { + echo " +
    +
    \n"); +} + + +// Site News +echo " +
    +
    \n"; + +show_news_for_page("HUB"); + +echo "
    \n"; + +$feedback_url = "$forums_url/viewtopic.php?f=3&t=388"; +echo " + + +
    +
      \n"; + +if ( $User->IsProjectManager() ) { + echo " +
    • " . link_to_project_manager("Manage My Projects") . "
    • \n"; +} + +// ---------------------------------- + +$acounts = array(); +$rows = $dpdb->SqlObjects(" + SELECT phase, COUNT(1) AS scount + FROM projects + GROUP BY phase + ORDER BY phase"); +foreach($rows as $row) { + $acounts[$row->phase] = $row->scount; +} + + + +// Providing Content +echo " +
    • " . _("Providing Content") + . "
      " + . _("Want to help out the site by providing material for us to proofread? ") + . "" + . _("Find out how!") + . " +
    • \n"; + +/** @var Round $round */ +foreach ( $Context->Rounds() as $round ) { + $roundid = $round->RoundId(); + $phase_icon_path = "$dyn_dir/stage_icons/$roundid.jpg"; + $phase_icon_url = "$dyn_url/stage_icons/$roundid.jpg"; + if ( file_exists($phase_icon_path) ) { + $round_img = "($roundid)"; + } + else { + $round_img = "($roundid)"; + } + $rname = RoundIdName($roundid); + $rdesc = RoundIdDescription($roundid); + $rlink = link_to_round($roundid, $rname); + + echo " +
    • +
      + $round_img $rlink
      $rdesc

      \n"; + + summarize_projects($roundid); +} + +$phase = "PP"; +$rname = NameForPhase($phase); +$rdesc = DescriptionForPhase($phase); +$rlink = link_to_pp($rname); +echo " +
    • +
      + ($phase) $rlink
      $rdesc

      \n"; +summarize_projects( $phase ); + +$n_checked_out = $dpdb->SqlOneValue(" + SELECT COUNT(1) FROM projects + WHERE postproofer='{$User->Username()}' + AND phase='PP'"); +if ($n_checked_out) { + echo sprintf( _("You currently have %d projects checked out in this phase."), $n_checked_out ); + echo "
      \n"; +} + + +$phase = "SR"; +$rname = _("Smooth Reading"); +$rdesc = _("Nearly completed projects are often made available for reading and checkproofing before posting."); +$rlink = link_to_smooth_reading($rname); +echo " +
    • +
      + ($phase) $rlink
      $rdesc

      \n"; + + +// ---------------------------------------------------- + +$phase = "PPV"; +$rname = NameForPhase($phase); +$rdesc = DescriptionForPhase($phase); +$rlink = link_to_ppv($rname); +echo " +
      +
    • ($phase) $rlink
      $rdesc

      \n"; +summarize_projects( $phase ); + +$n_checked_out = $dpdb->SqlOneValue(" + SELECT COUNT(1) FROM projects + WHERE ppverifier='{$User->Username()}' + AND phase='PPV'"); +if ($n_checked_out) { + echo sprintf( _("You currently have %d projects checked out in this phase."), $n_checked_out ); + echo "
      \n"; +} + +echo " +
    • +
    \n"; + + +theme("", "footer"); + +function summarize_projects( $phase) { + global $dpdb; + + if($phase == "P1" || $phase == "P2" || $phase == "P3" || $phase == "F1" || $phase == "F2") { + $row = $dpdb->SqlOneRow(" + SELECT SUM(CASE WHEN NOT EXISTS (SELECT 1 FROM project_holds + WHERE projectid = p.projectid + AND phase = '$phase') + THEN 1 ELSE 0 + END) navail, + COUNT(1) ntotal + FROM projects p WHERE p.phase = '$phase'"); + $navail = $row["navail"]; + $ntotal = $row["ntotal"]; + $nwaiting = $ntotal - $navail; + + echo _(" + + + + + + + +
    $nwaiting$navail$ntotal
    \n"); + return; + } + + + if($phase == "PP") { + $row = $dpdb->SqlOneRow(" + SELECT SUM(IFNULL(postproofer, '') = '') navail, + COUNT(1) ntotal, + SUM(smoothread_deadline > UNIX_TIMESTAMP() ) nsmooth + FROM projects where phase = '$phase'"); + $navail = $row["navail"]; + $ntotal = $row["ntotal"]; + $nchecked_out = $ntotal - $navail; + $nsmooth = $row["nsmooth"]; + echo _(" + + + + + + \n"); + echo " + +
    $navail$nchecked_out$nsmooth$ntotal
    \n"; + } + else { + $row = $dpdb->SqlOneRow(" + SELECT SUM(CASE WHEN IFNULL(ppverifier, '') = '' THEN 1 ELSE 0 END) navail, + COUNT(1) ntotal + FROM projects where phase = '$phase'"); + $navail = $row["navail"]; + $ntotal = $row["ntotal"]; + $nchecked_out = $ntotal - $navail; + echo _(" + + + + + \n"); + echo " + +
    $navail$nchecked_out$ntotal
    \n"; + } + + + +} + +function show_admin_links() { + global $User; + if(! $User->IsLoggedIn()) { + return; + } + echo " + + \n"; + +} diff --git a/c/ad_hoc.php b/c/ad_hoc.php new file mode 100644 index 0000000..4489858 --- /dev/null +++ b/c/ad_hoc.php @@ -0,0 +1,194 @@ +SqlRows(" + SELECT pagename, version FROM page_last_versions + WHERE projectid = '$projectid' + "); + +$str = ""; +foreach($pgs as $pg) { + $pagename = $pg['pagename']; + $version = $pg['version']; + $str .= PageVersionText( $projectid, $pagename, $version ); +} + +dump("text length: " . mb_strlen($str)); + +$Context->ZipSendString($projectid . "_PP", $str); +exit; + + +/* +$sql = "SELECT projectid, pagename, version, crc32, textlen + FROM page_versions"; + +$rows = $dpdb->SqlRows($sql); +foreach($rows as $row) { + dump($row); + $projectid = $row['projectid']; + $pagename = $row['pagename']; + $version = $row['version']; + $crc32 = $row['crc32']; + $textlen = $row['textlen']; + $text = PageVersionText($projectid, $pagename, $version); + $tcrc32 = (string) crc32($text); + $ttextlen = mb_strlen($text); + + $sql = "UPDATE page_versions SET crc32 = ?, textlen = ? + WHERE projectid = ? AND pagename = ? AND version = ?"; + $args = array(&$tcrc32, &$ttextlen, &$projectid, &$pagename, &$version); + $n = $dpdb->SqlExecutePS($sql, $args); + say("$projectid $pagename $version $crc32 $textlen $tcrc32 " . ($crc32 == $tcrc32 ? "same" : "not same") ); +} +exit; +*/ + + +//include "../c/pt.inc"; + + +//$projectid = 'p150813001'; +//$pagename = "001"; + +$project = new DpProject($projectid); + + +echo_page_table($project); +exit; +//$version = $project->AddPageVersionRow( "001", "P2", "PROOF", "A"); +//$project->ClonePageVersionText( "001" ); +//$project->AddPageVersionRows("P2", "PROOF", "A"); +$names = $project->PageNames(); +foreach($names as $pagename) { + $ret = $project->CloneLastVersionText($pagename); + dump($ret); +} +exit; + +dump($project->IsAvailable()); +dump($project->IsAvailableForActiveUser()); +dump($project->next_available_page_for_user()); +dump($project->next_retrievable_page_for_user()); +exit; +//$pagename = "312"; + +//$page = new DpPage($projectid, $pagename); +//dump($page->Text()); +//dump(text_lines($page->Text())); +//dump($project->ActiveText()); +//dump($project->EnchantedWords("en")); +//exit; + + +//dump($page->FlagWordsArray("en")); +//dump(PageVersionPath($projectid, $pagename, 1)); +//dump($project->ActivePageArray()); + + + +$project = new DpProject($projectid); +//dump($project->ActiveText()); +//$ew = $project->EnchantedWords("en", $project->ActiveText(), $project->ProjectId());; +//dump($ew->WordsArray()); +exit; + +dump($projectid); +dump($project->CompletedCount()); +dump($project->AvailableCount()); +dump($project->CheckedOutCount()); +$project->RecalcPageCounts(); +dump($project->CompletedCount()); +dump($project->AvailableCount()); +dump($project->CheckedOutCount()); +exit; +//$project->SetQueueHold("P1"); +//$project->SetQCHold("P1"); +/* +$projectid = "projectID51870bf940cce"; +$project = new DpProject($projectid); +dump(count($project->BadWordCountNotZero("en"))); + +include "wc/scannos.php"; +$s = array_keys($scannos); +//dump(array_slice($s,0,5)); +ksort($s); +// array(array(word, count)) +//$wds = $project->FlagWordsByCountAlpha("en"); +//dump(array_slice($wds, 0, 10)); + +// word => count +//$a = $project->RoundText("OCR"); +// which keys of scannos are in keys of counts +//dump($a); + +$pagetitle = "massive word check"; + +echo " + + + +$pagetitle + + + +
    \n"; + +$pids = $dpdb->SqlValues(" + SELECT p.projectid FROM projects p + JOIN phases ON p.phase = phases.phase + WHERE p.phase IN ('P2', 'P3', 'F1', 'F2') + AND p.language = 'en' + ORDER BY phases.sequence"); +say("Count " . count($pids) . " projects"); +$i = 0; + + +foreach($pids as $pid) { + $i++; + $proj = new DpProject($pid); + $phase = $proj->Phase(); + $title = $proj->NameOfWork(); + $words = text_to_words($proj->ActiveText()); + ksort($words); +// dump(array_slice($words,0,5)); +// dump(count(array_intersect($words, array("the"=>"the", "THE" => "THE")))); + $a = array_unique(array_intersect($words, $s)); +// dump(count($a)); +// die(); +// dump(memory_get_peak_usage()); +// $a = array_intersect($words, $s); +// dump(memory_get_peak_usage()); + if(count($a) > 0) { + dump("$i $pid $phase $title - " . count($a) . " of " . count($words)); + dump($a); + } +// $n1 = RegexCount('\\08D', "uis", $proj->RoundText("OCR")); +// $n2 = RegexCount('\\08D', "uis", $proj->RoundText("P1")); +// $n3 = RegexCount('\\08D', "uis", $proj->RoundText("P2")); +// $n4 = RegexCount('\\08D', "uis", $proj->RoundText("P3")); + +// if($n1 > 0 || $n2 > 0 || $n3 > 0 ) { +// say("$i $pid $n1 $n2 $n3"); +// } +// if($i >= 50) { +// break; +// } +} + + + + +say("
    "); + +*/ + + diff --git a/c/adhoc.html b/c/adhoc.html new file mode 100644 index 0000000..f7e79d6 --- /dev/null +++ b/c/adhoc.html @@ -0,0 +1,41 @@ + + + + + Use the mouse wheel on the field below. +
    +
    +
    +
    + The last roll amount: + diff --git a/c/admin.php b/c/admin.php new file mode 100644 index 0000000..db79d67 --- /dev/null +++ b/c/admin.php @@ -0,0 +1,61 @@ + $goal) { + if($goal > 0) { + $dpdb->SqlExecute(" + REPLACE INTO phase_goals + (phase, goal_date, goal) + VALUES + ('$phase', CURRENT_DATE(), $goal)"); + $dpdb->SqlExecute(" + UPDATE phase_goals + SET goal = '$goal' + WHERE phase = '$phase' + AND goal_date > CURRENT_DATE()"); + } +} + +$rows = $dpdb->SqlRows("SELECT pg.phase, pg.goal + FROM phase_goals pg + JOIN phases p ON pg.phase = p.phase + WHERE pg.goal_date = CURRENT_DATE() + ORDER BY p.sequence"); + +$tbl = new DpTable("tblgoals", "dptable lfloat"); +$tbl->addColumn("addColumn("^Goal", "goal"); +$tbl->addColumn("^New Goal", "phase", "eNewGoal"); +$tbl->SetRows($rows); + +echo $basic_header; +echo "

    Admin

    +
      +
    1. Here are the goal settings for today.
    2. +
    3. You can only change goals for today, but changes will affect the future as well.
    4. +
    5. Any new values you enter for a phase will change the goal for today and all future days.
    6. +
    7. Any values you leave blank will remain as they are.
    8. +
    +
    \n"; + +$tbl->EchoTable(); + +echo "
    + +
    + +"; +exit; + + +function eNewGoal($phase) { + return "\n"; +} + + diff --git a/c/ah.php b/c/ah.php new file mode 100644 index 0000000..d1d0924 --- /dev/null +++ b/c/ah.php @@ -0,0 +1,344 @@ +SqlObjects(" +SELECT DATE_FORMAT(d.dateval, '%m-%d') mmdd, + SUM(CASE WHEN round_id = 'P1' THEN page_count ELSE 0 END) p1count, + SUM(CASE WHEN round_id = 'P2' THEN page_count ELSE 0 END) p2count, + SUM(CASE WHEN round_id = 'P3' THEN page_count ELSE 0 END) p3count, + SUM(CASE WHEN round_id = 'F1' THEN page_count ELSE 0 END) f1count, + SUM(CASE WHEN round_id = 'F2' THEN page_count ELSE 0 END) f2count +FROM days d +JOIN user_round_pages urp + ON urp.count_time BETWEEN d.min_unixtime AND d.max_unixtime +WHERE d.dateval > DATE_SUB(CURRENT_DATE(), INTERVAL 1 MONTH) +GROUP BY d.dateval +ORDER BY d.dateval"); + +$data = array(); +$data[0] = array("Day", "P1", "P2", "P3", "F1", "F2"); + +foreach($rows as $row) { + $data[] = array($row->mmdd, $row->p1count, $row->p2count, + $row->p3count, $row->f1count, $row->f2count); +} + + +$dary = json_encode($data); +$dary = preg_replace("/\"(\d\d\d)\"/", "$1", $dary); + + +$ahtitle = _("Activity Hub"); + +echo +" + + + + +DPC: Activity Hub + + + + + + + + +\n"; + +// theme($ahtitle, "header"); +html_logobar($ahtitle); + +echo " +
    + $ahtitle +
    \n"; + + +if($User->IsSiteManager() || $User->IsProjectFacilitator() || $User->IsProjectManager()) { + echo " + + +
    +
    + \n"; +} + +$pagecount = $User->PageCount(); +echo _("

    Welcome to the DP Activity Hub. From this page you can view the +phases of DP production. Follow the links to the specific areas of the site.

    "); + + +if ($pagecount <= 300) { + if ($User->InboxCount() > 0) { + echo + "
    +
    \n"; + + echo _(" +

    You have received a private message in your Inbox!

    "); + echo _("

    This could be from somebody sending you feedback on some of the + pages you had proofread earlier. We strongly recommend you READ your + messages. In the links at the top of this page, there is one that says + My Inbox. Just click on that to open your Inbox.

    "); + echo _("

    (After a while this explanatory paragraph will not appear when + you have new messages, but the link to your Inbox will always be up + there and when you have new messages that will be shown in the link)

    "); + echo "
    "; + } +} + + + +if ($pagecount <= 100) { + echo " +
    +
    +

    " + ._("Welcome") + ."

    \n" + ._("

    Please see our ") ."" + ._("Beginner's Forum") + ."". _(" for answers to common questions.

    +
    \n"); +} + + +// Site News +echo " +
    +
    \n"; + +show_news_for_page("HUB"); + +echo "
    \n"; + +$feedback_url = "$forums_url/viewtopic.php?f=3&t=388"; +echo " +\n"; + + +// Show any mentor banners. +if($User->MayMentor()) { + mentor_banner($round); +} +// ============================================================================= + +echo " +
    +
      \n"; + +if ( user_is_PM() ) { + echo " +
    • " . link_to_project_manager("Manage My Projects") . "
    • \n"; +} + +// ---------------------------------- + +$acounts = array(); +$rows = $dpdb->SqlObjects(" + SELECT phase, COUNT(1) AS scount + FROM projects + GROUP BY phase + ORDER BY phase"); +foreach($rows as $row) { + $acounts[$row->phase] = $row->scount; +} + + + +// Providing Content +echo " +
    • " . _("Providing Content") + . "
      " + . _("Want to help out the site by providing material for us to proofread? ") + . "" + . _("Find out how!") + . " +
    • \n"; + +foreach ( $Context->Rounds() as $roundid ) { + $phase_icon_path = "$dyn_dir/stage_icons/$roundid.jpg"; + $phase_icon_url = "$dyn_url/stage_icons/$roundid.jpg"; + if ( file_exists($phase_icon_path) ) { + $round_img = "($roundid)"; + } + else { + $round_img = "($roundid)"; + } + $rname = RoundIdName($roundid); + $rdesc = RoundIdDescription($roundid); + $rlink = link_to_round($roundid, $rname); + + echo " +
    • +
      + $round_img $rlink
      $rdesc

      \n"; + + summarize_projects($roundid); +} + +$phase = "PP"; +$rname = NameForPhase($phase); +$rdesc = DescriptionForPhase($phase); +$rlink = link_to_pp($rname); +echo " +
    • +
      + ($phase) $rlink
      $rdesc

      \n"; +summarize_projects( $phase ); + +$n_checked_out = $dpdb->SqlOneValue(" + SELECT COUNT(1) FROM projects + WHERE postproofer='{$User->Username()}' + AND phase='PP'"); +if ($n_checked_out) { + echo sprintf( _("You currently have %d projects checked out in this phase."), $n_checked_out ); + echo "
      \n"; +} + +// ---------------------------------------------------- + +$phase = "PPV"; +$rname = NameForPhase($phase); +$rdesc = DescriptionForPhase($phase); +$rlink = link_to_ppv($rname); +echo " +
      +
    • ($phase) $rlink
      $rdesc

      \n"; +summarize_projects( $phase ); + +$n_checked_out = $dpdb->SqlOneValue(" + SELECT COUNT(1) FROM projects + WHERE ppverifier='{$User->Username()}' + AND phase='PPV'"); +if ($n_checked_out) { + echo sprintf( _("You currently have %d projects checked out in this phase."), $n_checked_out ); + echo "
      \n"; +} + +echo " +
    • +
    \n"; + + +theme("", "footer"); + +function summarize_projects( $phase) { + global $dpdb; + + if($phase == "P1" || $phase == "P2" || $phase == "P3" || $phase == "F1" || $phase == "F2") { + $row = $dpdb->SqlOneRow(" + SELECT SUM(CASE WHEN NOT EXISTS (SELECT 1 FROM project_holds + WHERE projectid = p.projectid + AND phase = '$phase') + THEN 1 ELSE 0 + END) navail, + COUNT(1) ntotal + FROM projects p WHERE p.phase = '$phase'"); + $navail = $row["navail"]; + $ntotal = $row["ntotal"]; + $nwaiting = $ntotal - $navail; + + echo _(" + + + + + + + +
    $nwaiting$navail$ntotal
    \n"); + return; + } + + if($phase == "PP") { + $row = $dpdb->SqlOneRow(" + SELECT SUM(CASE WHEN IFNULL(postproofer, '') = '' THEN 1 ELSE 0 END) navail, + COUNT(1) ntotal + FROM projects where phase = '$phase'"); + } + else { + $row = $dpdb->SqlOneRow(" + SELECT SUM(CASE WHEN IFNULL(ppverifier, '') = '' THEN 1 ELSE 0 END) navail, + COUNT(1) ntotal + FROM projects where phase = '$phase'"); + } + $navail = $row["navail"]; + $ntotal = $row["ntotal"]; + $nchecked_out = $ntotal - $navail; + + echo _(" + + + + + + + +
    $navail$nchecked_out$ntotal
    \n"); + + +} + +?> diff --git a/c/backlog.php b/c/backlog.php new file mode 100644 index 0000000..cac8610 --- /dev/null +++ b/c/backlog.php @@ -0,0 +1,57 @@ +SqlObjects(" + SELECT p.phase, + COUNT(1) nprojects, + SUM(n_pages) npages, + ROUND(SUM(n_pages) / pg.goal) ndays + FROM projects p + JOIN phases ph ON p.phase = ph.phase + JOIN phase_goals pg ON p.phase = pg.phase + AND pg.goal_date = CURRENT_DATE() + WHERE p.phase IN ('P1', 'P2', 'P3', 'F1', 'F2') + GROUP BY p.phase + ORDER BY sequence"); + + +?> + + + + google.load("visualization", "1", {packages:["corechart"]}); + google.setOnLoadCallback(drawChart); + + function drawChart() { + var chart = new google.visualization.ColumnChart(document.getElementById('chart_div')); + var data = new google.visualization.DataTable(); + data.addColumn('string', 'Phase'); + data.addColumn('number', 'Days (@ Goal)'); + data.addColumn('number', 'Pages'); +phase', + $phase->ndays, + $phase->npages]);\n"; + } +?> + chart.draw(data, { + title: "Round Pool Size (Pages and Days at Goal)", + curveType: "function", + width: 300, + height: 200, + vAxes: {0: {logScale: false}, + 1: {logScale: false}}, + series:{ + 0:{targetAxisIndex:0}, + 1:{targetAxisIndex:1}}} + ); + } + + + +
    + + diff --git a/c/browse.php b/c/browse.php new file mode 100644 index 0000000..172c65f --- /dev/null +++ b/c/browse.php @@ -0,0 +1,33 @@ +Exists() + or die("No such project - $projectid"); + +$pages = $project->PageRows(); +$pgsrc = url_for_page_image($projectid, $pages[0]["image"]); + +echo " + + + + {$project->Title()} + + +
    + +
    + +
    + \n"; +} + +function url_for_upload_widget($projectid = "", $pagename = "") { + global $code_url; + return "$code_url/upwidget.php" + ."?projectid=$projectid" + ."&pagename=$pagename"; +} + +// -- fadedpage + +function url_for_fadedpage_catalog( $postednum ) { + return "http://www.fadedpage.com/showbook.php?pid={$postednum}"; +} + +function link_to_fadedpage_catalog( $postednum, $prompt="FadedPage" ) { + return link_to_url(url_for_fadedpage_catalog($postednum), $prompt); +} +function url_for_fadedpage() { + return "http://www.fadedpage.com"; +} +function link_to_fadedpage( $prompt = "FadedPage" ) { + return link_to_url(url_for_fadedpage(), $prompt); +} + +/** + * Members + */ + + +function link_to_member_list($prompt = "") { + return link_to_url(url_for_member_list(), $prompt); +} + +function url_for_member_list() { + global $code_url; + return "$code_url/stats/members/member_list.php"; +} + + +function link_to_member_stats($username, $prompt = "") { + return link_to_url(url_for_member_stats($username), $prompt); +} + +function url_for_member_stats($username) { + global $code_url; + return "$code_url/stats/members/member_stats.php" + . "?username=$username"; +} + +function url_for_team_stats($tid, $roundid = "") { + global $code_url; + return $roundid + ? "$code_url/stats/teams/tdetail.php?tid=$tid&roundid=$roundid" + : "$code_url/stats/teams/tdetail.php?tid=$tid"; +} + +function link_to_team_stats($tid, $roundid, $prompt = "") { + if($prompt == "") { + $prompt = $roundid; + } + return link_to_url(url_for_team_stats($tid, $roundid), $prompt); +} + +function link_to_user_roles($username, $prompt = null) { + if(! $prompt) $prompt = $username; + return link_to_url(url_for_user_roles($username), $prompt); +} + +function url_for_user_roles($username) { + global $code_url; + return build_path($code_url, "tools/site_admin/user_roles.php" + ."?username=$username" + ."&qrysubmituser=1"); +} + +function link_to_round_stats($round, $prompt = "") { + if(! $prompt) $prompt = $round; + return link_to_url(url_for_round_stats($round), $prompt); +} + +function url_for_round_stats($round) { + global $code_url; + return "$code_url/stats/proof_stats.php?roundid=$round"; +} + +function link_to_round_charts($round, $prompt = "") { + if(! $prompt) $prompt = $round; + return link_to_url(url_for_round_charts($round), $prompt); +} + +function url_for_round_charts($round) { + global $code_url; + return "$code_url/stats/pages_proofed_graphs.php?roundid=$round"; +} + +function link_to_misc_stats($round, $prompt = "") { + if(! $prompt) $prompt = $round; + return link_to_url(url_for_misc_stats($round), $prompt); +} + +function url_for_misc_stats($round) { + global $code_url; + return "$code_url/stats/misc_stats1.php?roundid=$round"; +} + +function url_for_create_team() { + global $code_url; + return "$code_url/stats/teams/new_team.php"; +} + +function link_to_create_team($prompt = "Create a new team") { + return link_to_url(url_for_create_team(), $prompt); +} + +function url_for_metal_list($metal) { + global $code_url; + return "$code_url/list_etexts.php?{$metal}"; +} + +function link_to_metal_list($metal, $prompt = "", $isnew=false) { + if(!$prompt) $prompt = $metal; + return link_to_url(url_for_metal_list($metal), $prompt, $isnew ); +} + +// -- wordcontext + +function url_for_word_context($projectid, $mode, $options = "") { + global $wc_url; + return "$wc_url/wordcontext.php" + ."?projectid={$projectid}" + ."&mode={$mode}" + . (($options) ? "&$options" : ""); +} + +function url_for_ad_hoc_word_context($projectid) { + return url_for_word_context($projectid, "adhoc"); +} + +function url_for_flagged_word_context($projectid) { + return url_for_word_context($projectid, "aspell"); +} + + + +// -- wordcheck flags (word context) + +function link_to_wordcheck_flags( + $projectid, $prompt, $is_new_tab = false) { + return link_to_url( + url_for_wordcheck_flags($projectid), $prompt, $is_new_tab); +} + +function url_for_wordcheck_flags($projectid) { + return url_for_word_context($projectid, "flagged"); +} + +// -- wordcheck stats + +function link_to_wordcheck_stats($projectid, $prompt) { + return link_to_url( url_for_wordcheck_stats($projectid), $prompt); +} + +function url_for_wordcheck_stats($projectid) { + global $wc_url; + return "$wc_url/wordcheck_stats.php?projectid=$projectid"; +} + +// -- ad hoc words + +function link_to_regex_words($projectid, $prompt) { + return link_to_url(url_for_regex_words($projectid), $prompt); +} + +function url_for_regex_words($projectid) { + return url_for_word_context($projectid, "regex"); +} + +// -- ad hoc words + +function link_to_adhoc_words($projectid, $prompt) { + return link_to_url(url_for_adhoc_words($projectid), $prompt); +} + +function url_for_adhoc_words($projectid) { + return url_for_word_context($projectid, "adhoc"); +} + +// -- wdiff + +function link_to_wdiff_results($projectid, $langcode, $prompt) { + return link_to_url( + url_for_wdiff_results($projectid, $langcode), $prompt); +} + +function url_for_wdiff_results($projectid, $langcode) { + global $wc_url; + return "$wc_url/wdiff.php?projectid=$projectid" + ."&langcode=$langcode"; +} + +// -- hyphenated words + +function link_to_hyphenated_words($projectid, $prompt) { + return link_to_url( + url_for_hyphenated_words($projectid), $prompt); +} + +function url_for_hyphenated_words($projectid) { + return url_for_word_context($projectid, "hyphenated"); +} + + +// -- diff suggestions + +function link_to_diff_suggestions($projectid, $prompt) { + return link_to_url( + url_for_diff_suggestions($projectid), $prompt); +} + +function url_for_diff_suggestions($projectid) { + global $wc_url; + return "$wc_url/scannos.php?projectid=$projectid"; +} + + +// -- good words + +function link_to_good_words( + $projectid, $prompt, $is_new_tab = false) { + return link_to_url(url_for_good_words($projectid), $prompt, + $is_new_tab); +} + +function url_for_good_words($projectid) { + return url_for_word_context($projectid, "good"); +} + +// -- suggested words + +function link_to_suggested_words( + $projectid, $prompt, $is_new_tab = false) { + return link_to_url( + url_for_suggested_words($projectid), $prompt, $is_new_tab); +} + +function url_for_suggested_words($projectid) { + return url_for_word_context($projectid, "suggested"); +} + +// -- suspect words + +function link_to_suspect_words($projectid, $prompt, $is_new_tab = false) { + return link_to_url(url_for_suspect_words($projectid), $prompt, + $is_new_tab); +} + +function url_for_suspect_words($projectid) { + return url_for_word_context($projectid, "suspect"); +} + +function link_to_refresh_suspect_words($projectid, $prompt, + $is_new_tab = false, $options) { + return link_to_url(url_for_refresh_suspect_words($projectid, $options), + $prompt, $is_new_tab); +} + +function url_for_refresh_suspect_words($projectid, $options) { + return url_for_word_context($projectid, "suspect", $options); +} + +// -- bad words + +function link_to_bad_words($projectid, $prompt, $is_new_tab = false) { + return link_to_url(url_for_bad_words($projectid), $prompt, + $is_new_tab); +} + +function url_for_bad_words($projectid) { + return url_for_word_context($projectid, "bad"); +} + +function link_to_project_words($projectid, $prompt="Words", $newtab = false) { + return link_to_url( url_for_project_words($projectid), $prompt, $newtab); +} + +function url_for_project_words($projectid) { + global $wc_url; + return "$wc_url/project_words.php" + ."?projectid={$projectid}"; +} diff --git a/c/pinc/list_projects.inc b/c/pinc/list_projects.inc new file mode 100644 index 0000000..aeea572 --- /dev/null +++ b/c/pinc/list_projects.inc @@ -0,0 +1,68 @@ +SqlOneValue(" + SELECT COUNT(1) FROM projects + $where"); +} + +// List the specified projects, +// giving brief information about each. +function list_projects( $metal, $limit = "20", $sort = "title", $dir = "A") { + global $dpdb; + + $dir = $dir == "A" ? "ASC" : "DESC"; + $where = metal_where($metal); + $rows = $dpdb->SqlRows(" + SELECT *, + nameofwork title, + authorsname author, + DATE(FROM_UNIXTIME(phase_change_date)) moddate + FROM projects + $where + ORDER BY $sort $dir + LIMIT $limit"); + + echo "
    "; + echo "\n"; + + $counter = 0; + foreach($rows as $project) { + $counter++; + $title = maybe_convert($project['nameofwork']); + $author = maybe_convert($project['authorsname']); + $language = $project['language']; + $n_pages = $project["n_pages"]; + $moddate = $project["moddate"]; + $postednum = $project['postednum']; + + echo "$counter) \"$title\" $author ($language)
    + " . _("$n_pages pages; ") . "$moddate
    \n"; + // Download info + if ( !$postednum ) { + echo link_to_fadedpage_catalog($postednum) . "

    \n"; + } + } +} +// vim: sw=4 ts=4 expandtab diff --git a/c/pinc/lists.php b/c/pinc/lists.php new file mode 100644 index 0000000..7fd80b8 --- /dev/null +++ b/c/pinc/lists.php @@ -0,0 +1,501 @@ + _("Undefined"), + "proof" => _("Proof"), + "reproof" => _("Reproof"), + "markup" => _("Markup"), + "check" => _("Check"), + "special" => _("Special"), + "complete" => _("Complete"), + "test" => _("Test") +// "easy" => _("Easy"), +// "average" => _("Average"), +// "hard" => _("Difficult") +); +*/ + +$site_difficulties = array( + "easy" => _("Easy"), + "average" => _("Average"), + "hard" => _("Hard") +); + +$site_languages = array( + "eng" => _("English"), + "fra" => _("French"), + "deu" => _("German"), + "ita" => _("Italian"), + "hun" => _("Hungarian"), + "tur" => _("Turkish"), + "esp" => _("Spanish"), + "por" => _("Portuguese"), + "lat" => _("Latin"), + "dut" => _("Dutch"), + "dan" => _("Danish"), + "swe" => _("Swedish"), + "grc" => _("Greek, Ancient"), + "gla" => _("Gaelic"), + "heb" => _("Hebrew"), + "epo" => _("Esperanto"), + "sco" => _("Scots"), + "pol" => _("Polish"), + "san" => _("Sanskrit") +); + + +$font_faces = array('courier' => 'Courier New', + 'times' => 'Times', + 'arial' => 'Arial', + 'monospaced' => 'monospace', + 'dpcustommono2' => 'DPCustomMono2', + 'lucidaconsole' => 'Lucida Console', + 'dejavu' => 'DejaVu Sans Mono', + 'monaco' => 'Monaco'); + +$font_sizes = array( + '8pt' => '8pt' , + '9pt' => '9pt' , + '10pt' => '10pt', + '11pt' => '11pt', + '12pt' => '12pt', + '13pt' => '13pt', + '14pt' => '14pt', + '15pt' => '15pt', + '16pt' => '16pt', + '18pt' => '18pt', + '20pt' => '20pt', + '24pt' => '24pt', + '30pt' => '30pt' + ); + +$site_genres = array( + 'Other' => _('Other'), + 'Adventure' => _('Adventure'), + 'Agriculture' => _('Agriculture'), + 'Archaeology' => _('Archaeology'), + 'Art' => _('Art'), + 'Animals' => _('Animals'), + 'Anthropology' => _('Anthropology'), + 'Architecture' => _('Architecture'), + 'Astronomy' => _('Astronomy'), + 'Autobiography' => _('Autobiography'), + 'Bibliography' => _('Bibliography'), + 'Biography' => _('Biography'), + 'Biology' => _('Biology'), + 'Business' => _('Business'), + 'Chemistry' => _('Chemistry'), + 'Collection' => _('Collection'), + 'Comics' => _('Comics'), + 'Cooking' => _('Cooking'), + 'Correspondence' => _('Correspondence'), + 'Crafts' => _('Crafts'), + 'Diary' => _('Diary'), + 'Dictionary' => _('Dictionary'), + 'Drama' => _('Drama'), + 'Economics' => _('Economics'), + 'Education' => _('Education'), + 'Encyclopedia' => _('Encyclopedia'), + 'Engineering' => _('Engineering'), + 'Essay' => _('Essay'), + 'Folklore' => _('Folklore'), + 'General Fiction' => _('General Fiction'), + 'Geography' => _('Geography'), + 'Geology' => _('Geology'), + 'Grammar' => _('Grammar'), + 'Health' => _('Health'), + 'History' => _('History'), + 'Historical Fiction' => _('Historical Fiction'), + 'Horror' => _('Horror'), + 'Horticulture' => _('Horticulture'), + 'Humor' => _('Humor'), + 'Instructional' => _('Instructional'), + 'Juvenile' => _('Juvenile'), + 'Law' => _('Law'), + 'Linguistics' => _('Linguistics'), + 'Literature' => _('Literature'), + 'Mathematics' => _('Mathematics'), + 'Medicine' => _('Medicine'), + 'Military' => _('Military'), + 'Mixed Form' => _('Mixed Form'), + 'Monograph' => _('Monograph'), + 'Music' => _('Music'), + 'Musicology' => _('Musicology'), + 'Mystery' => _('Mystery'), + 'Mythology' => _('Mythology'), + 'Nature' => _('Nature'), + 'Natural Science' => _('Natural Science'), + 'Non-Fiction' => _('Non-Fiction'), + 'Periodical' => _('Periodical'), + 'Philosophy' => _('Philosophy'), + 'Physics' => _('Physics'), + 'Picture Book' => _('Picture Book'), + 'Poetry' => _('Poetry'), + 'Political Science' => _('Political Science'), + 'Psychology' => _('Psychology'), + 'Recreation' => _('Recreation'), + 'Religious' => _('Religious'), + 'Reference' => _('Reference'), + 'Romance' => _('Romance'), + 'Satire' => _('Satire'), + 'Science' => _('Science'), + 'Science Fiction' => _('Science Fiction'), + 'Short Story' => _('Short Story'), + 'Sociology' => _('Sociology'), + 'Speech' => _('Speech'), + 'Spirituality' => _('Spirituality'), + 'Sports' => _('Sports'), + 'Technology' => _('Technology'), + 'Travel' => _('Travel'), + 'Veterinary' => _('Veterinary'), + 'Western' => _('Western'), + 'Zoology' => _('Zoology'), +); + +// these languages may be associated with projects +// should be in the order to be displayed as a list +$_active_languages_array_2 = array( + "it", "nl", "eo", "en", "fi", "fr", "de", "de-alt", "la", + "pt", "es", "sv", "ar", "bn", "bg", "ca", "cs", + "da", "el", "et", "eu", + "fo", "fa", "ga", "gl", "grc", "he", + "hi", "hr", "hu", "hy", "is", "it", "ku", "lv", + "lt", "nn", "nb", "no", "pl", "ro", + "ru", "sr", "hr", "sk", "sl", + "ta", "te", "tl", "uk", "und", "cy"); + +$wclangs = array( + "cs" => "Czech", + "da" => "Danish", + "nl" => "Dutch", + "en" => "English", + "fi" => "Finnish", + "fr" => "French", + "de" => "German", + "grc" => "Greek ancient", + "el" => "Greek modern", + "eo" => "Esperanto", + "he" => "Hebrew", + "it" => "Italian", + "la" => "Latin", + "no" => "Norwegian", + "pt" => "Portuguese", + "sk" => "Slovak", + "es" => "Spanish", + "sv" => "Swedish" +); + +$lang_codes = array( + "ab" => "Abkhazian", + "aa" => "Afar", + "af" => "Afrikaans", + "ak" => "Akan", + "sq" => "Albanian", + "am" => "Amharic", + "ar" => "Arabic", + "an" => "Aragonese", + "hy" => "Armenian", + "as" => "Assamese", + "av" => "Avaric", + "ae" => "Avestan", + "ay" => "Aymara", + "az" => "Azerbaijani", + "bm" => "Bambara", + "ba" => "Bashkir", + "eu" => "Basque", + "be" => "Belarusian", + "bn" => "Bengali", + "bh" => "Bihari", + "bi" => "Bislama", + "nb" => "Bokmål", + "bs" => "Bosnian", + "br" => "Breton", + "bg" => "Bulgarian", + "my" => "Burmese", + "ca" => "Catalan", + "km" => "Central Khmer", + "ch" => "Chamorro", + "ce" => "Chechen", + "ny" => "Chichewa", + "zh" => "Chinese", + "cv" => "Chuvash", + "kw" => "Cornish", + "co" => "Corsican", + "cr" => "Cree", + "hr" => "Croatian", + "cs" => "Czech", + "da" => "Danish", + "dv" => "Divehi", + "nl" => "Dutch", + "dz" => "Dzongkha", + "en" => "English", + "eo" => "Esperanto", + "et" => "Estonian", + "ee" => "Ewe", + "fo" => "Faroese", + "fj" => "Fijian", + "fi" => "Finnish", + "fr" => "French", + "fy" => "Frisian", + "ff" => "Fulah", + "gd" => "Gaelic", + "gl" => "Galician", + "lg" => "Ganda", + "ka" => "Georgian", + "de" => "German", + "de-alt" => "German (de-alt)", + "grc" => "Greek ancient", + "el" => "Greek modern", + "gn" => "Guarani", + "gu" => "Gujarati", + "ht" => "Haitian", + "ha" => "Hausa", + "he" => "Hebrew", + "hz" => "Herero", + "hi" => "Hindi", + "ho" => "Hiri Motu", + "hu" => "Hungarian", + "is" => "Icelandic", + "io" => "Ido", + "ig" => "Igbo", + "id" => "Indonesian", + "ia" => "Interlingua", + "ie" => "Interlingue", + "iu" => "Inuktitut", + "ik" => "Inupiaq", + "ga" => "Irish", + "it" => "Italian", + "ja" => "Japanese", + "jv" => "Javanese", + "kl" => "Kalaallisut", + "kn" => "Kannada", + "kr" => "Kanuri", + "ks" => "Kashmiri", + "kk" => "Kazakh", + "ki" => "Kikuyu", + "rw" => "Kinyarwanda", + "ky" => "Kirghiz", + "kv" => "Komi", + "kg" => "Kongo", + "ko" => "Korean", + "kj" => "Kuanyama", + "ku" => "Kurdish", + "lo" => "Lao", + "la" => "Latin", + "lv" => "Latvian", + "li" => "Limburgan", + "ln" => "Lingala", + "lt" => "Lithuanian", + "lu" => "Luba-Katanga", + "lb" => "Luxembourgish", + "mk" => "Macedonian", + "mg" => "Malagasy", + "ms" => "Malay", + "ml" => "Malayalam", + "mt" => "Maltese", + "gv" => "Manx", + "mi" => "Maori", + "mr" => "Marathi", + "mh" => "Marshallese", + "mn" => "Mongolian", + "na" => "Nauru", + "nv" => "Navajo", + "nd" => "Ndebele N.", + "nr" => "Ndebele S.", + "ng" => "Ndonga", + "ne" => "Nepali", + "no" => "Norwegian", + "nn" => "Norwegian Nynorsk", + "oc" => "Occitan", + "oj" => "Ojibwa", + "or" => "Oriya", + "om" => "Oromo", + "os" => "Ossetian", + "pi" => "Pali", + "pa" => "Panjabi", + "fa" => "Persian", + "pl" => "Polish", + "pt" => "Portuguese", + "ps" => "Pushto", + "qu" => "Quechua", + "ro" => "Romanian", + "rm" => "Romansh", + "rn" => "Rundi", + "ru" => "Russian", + "se" => "Sami N", + "sm" => "Samoan", + "sg" => "Sango", + "sa" => "Sanskrit", + "sc" => "Sardinian", + "sr" => "Serbian", + "sn" => "Shona", + "ii" => "Sichuan Yi", + "sd" => "Sindhi", + "si" => "Sinhala", + "cu" => "Slavic", + "sk" => "Slovak", + "sl" => "Slovenian", + "so" => "Somali", + "st" => "Sotho", + "es" => "Spanish", + "su" => "Sundanese", + "sw" => "Swahili", + "ss" => "Swati", + "sv" => "Swedish", + "tl" => "Tagalog", + "ty" => "Tahitian", + "tg" => "Tajik", + "ta" => "Tamil", + "tt" => "Tatar", + "te" => "Telugu", + "th" => "Thai", + "bo" => "Tibetan", + "ti" => "Tigrinya", + "to" => "Tonga", + "ts" => "Tsonga", + "tn" => "Tswana", + "tr" => "Turkish", + "tk" => "Turkmen", + "tw" => "Twi", + "ug" => "Uighur", + "uk" => "Ukrainian", + "und" => "Undeterminate", + "ur" => "Urdu", + "uz" => "Uzbek", + "ve" => "Venda", + "vi" => "Vietnamese", + "vo" => "Volapük", + "wa" => "Walloon", + "cy" => "Welsh", + "wo" => "Wolof", + "xh" => "Xhosa", + "yi" => "Yiddish", + "yo" => "Yoruba", + "za" => "Zhuang", + "zu" => "Zulu", +); + +$Honorifics = array( + "P1" => array( + 0 => _('Novice'), + 25 => _('Proofreading Pupil'), + 100 => _('Proofreading Apprentice'), + 500 => _('Proofreading Scholar'), + 1000 => _('Proofreading Prodigy'), + 2500 => _('Prefect of Proofreaders'), + 5000 => _('Proofreading Graduate'), + 10000 => _('Proofreading Alumnus'), + 20000 => _('Fellow of Proofreading'), + 30000 => _('Doctor of Proofreading'), + 40000 => _('Proofreading Don'), + 50000 => _('Dean of Proofreading'), + 60000 => _('Proofreading Proctor'), + 70000 => _('Principal Proofreader'), + 80000 => _('Master Proofreader'), + 90000 => _('Prefect of Proofreaders'), + 99000 => _('Supervising Proofreader'), + 100000 => _('Proofreading Professor'), + 110000 => _('Peer of Proofreading'), + 120000 => _('Doyen of Proofreading'), + 130000 => _('Proofreading Chancellor'), + 140000 => _('Proofreading Primate'), + 150000 => _('Paramount Proofreader')), + + "P2" => array( + 0 => _('Precise Proofreader'), + 25 => _('Picky Proofreader'), + 100 => _('Painstaking Proofreader'), + 500 => _('Punctilious Proofreader'), + 1000 => _('Persnickety Proofreader'), + 2500 => _('Particular Proofreader'), + 5000 => _('Proficient Proofreader'), + 10000 => _('Proper Proofreader'), + 20000 => _('Prudent Proofreader'), + 30000 => _('Proofreading Personage'), + 40000 => _('Proofreading Poppet'), + 50000 => _('Plighted Proofreader'), + 60000 => _('Proofreading Proctor'), + 70000 => _('Principal Proofreader'), + 80000 => _('Prime Proofreader'), + 90000 => _('Primal Proofreader'), + 99000 => _('Proofreading Personality'), + 100000 => _('Proofreading Professional'), + 110000 => _('Peerless Proofreader'), + 120000 => _('Plighted Proofreader'), + 130000 => _('Paraproofreader'), + 140000 => _('Proofreading Panjandrum'), + 150000 => _('Perfectionist Proofreader')), + "P3" => array( + 0 => _('Specialist Proofreader'), + 25 => _('Precious Proofreader'), + 100 => _('Prized Proofreader'), + 500 => _('Premiere Proofreader'), + 1000 => _('Proofreading Perfectionist'), + 2500 => _('Pillar of Proofreading'), + 5000 => _('Proofreading Purist'), + 10000 => _('Proofreader of Precision'), + 20000 => _('Archetypal Proofreader'), + 30000 => _('Proofreading Nonpareil'), + 40000 => _('Paradigmatic Proofreader'), + 50000 => _('Preeminent Proofreader'), + 60000 => _('Prime Proofreader'), + 70000 => _('Proofreader of Plenariness'), + 80000 => _('Perpetual Proofreader'), + 90000 => _('Prefect of Proofreaders'), + 99000 => _('Impeccable Proofreader'), + 100000 => _('Proofreader of Persistence'), + 110000 => _('Patent Proofreader'), + 120000 => _('Proofreading Philosopher'), + 130000 => _('Patron of Proofreaders'), + 140000 => _('Proofreading Partner'), + 150000 => _('Pioneer of Proofreaders')), + "F1" => array( + 0 => _('Formatting Neophyte'), + 25 => _('Formatting Intern'), + 100 => _('Journeyman Formatter'), + 500 => _('Crafter of Texts'), + 1000 => _('Detailer of Books'), + 2500 => _('Fastidious Formatter'), + 5000 => _('Foremost Formatter'), + 10000 => _('Fine Formatter'), + 20000 => _('Flamboyant Formatter'), + 30000 => _('Fabulous Formatter'), + 40000 => _('Upgrader of Texts'), + 50000 => _('Famous Formatter'), + 60000 => _('Indefatigible Formatter'), + 70000 => _('Finisher of Texts'), + 80000 => _('Formatter of Choice'), + 90000 => _('Capital Formatter'), + 99000 => _('Formatter with Flair'), + 100000 => _('Formatter of Finesse'), + 110000 => _('Formatter with Forte'), + 120000 => _('First-Class Formatter'), + 130000 => _('Formatter of Favour'), + 140000 => _('Formatter of Refinement'), + 150000 => _('Flawless Formatter')), + + "F2" => array( + 0 => _('Refurbisher of Texts'), + 25 => _('Sprucer of Texts'), + 100 => _('Formatter Savant'), + 500 => _('Formatting Wunderkind'), + 1000 => _('Elite Formatter'), + 2500 => _('Polisher of Texts'), + 5000 => _('Formatting Artiste'), + 10000 => _('Cultivator of Texts'), + 20000 => _('Formatter of Enrichment'), + 30000 => _('Designing Formatter'), + 40000 => _('Formatting Artisan'), + 50000 => _('Formatting Afficiando'), + 60000 => _('Guru of Formatters'), + 70000 => _('Formatting Familiar'), + 80000 => _('Formatting Virtuoso'), + 90000 => _('Formatter of Excellence'), + 99000 => _('Exquisite Formatter'), + 100000 => _('Elite Formatter'), + 110000 => _('Formatting Genius'), + 120000 => _('Formatter of Fine Feats'), + 130000 => _('Harmoniser of Texts'), + 140000 => _('Formatting Architect'), + 150000 => _('Preserver of Texts')) +); diff --git a/c/pinc/maintenance_mode.inc b/c/pinc/maintenance_mode.inc new file mode 100644 index 0000000..7128463 --- /dev/null +++ b/c/pinc/maintenance_mode.inc @@ -0,0 +1,23 @@ +

    $pguser $message

    "; + exit(); + } + } +} + +// vim: sw=4 ts=4 expandtab +?> diff --git a/c/pinc/marc_format.inc b/c/pinc/marc_format.inc new file mode 100644 index 0000000..05d4fbc --- /dev/null +++ b/c/pinc/marc_format.inc @@ -0,0 +1,270 @@ + "Art", "b" => "Biography", 3 => "Comedy", "c" => "Comic Strip", 4 => "Cooking", "d" => "Drama", "e" => "Essay", 1 => "Fiction", "g" => "Geography", 5 => "Historical", 6 => "History", 7 => "Humor", 'Humor', "i" => "Letter", "l" => "Linquistics", 8 => "Math", 9 => "Medicine", "m" => "Mixed Form", "v" => 'Music', 0 => "Non Fiction", "f" => "Novel", "y" => "Periodical", "p" => "Poetry", "r" => "Romance", "z" => "Science", "h" => "Satire", "j" => "Short Story", "s" => "Speech", "u" => "Unknown", "|" => "Unknown"); + +function marc_key_search($rec, $tag, $subfield) { + foreach ($rec as $key => $value) { + if (!empty($subfield)) { + if (preg_match("/^\(3,$tag\)\(3,[0123456789[:space:]]+\)\(3,$subfield\)$/", $value[0])) { + return $key; + } + } else { + if (preg_match("/^\(3,$tag\)\(3,[0123456789@[:space:]]+\)$/", $value[0])) { + return $key; + } + } + } +} + +function marc_title($rec) { + $marc_title = $rec[marc_key_search($rec,"245","a")][1]; + $marc_title = trim(preg_replace("/\/$|:$/", "", $marc_title)); + $marc_edition = $rec[marc_key_search($rec,"250","a")][1]; + $marc_edition = trim($marc_edition); + + if (isset($marc_edition)) { $marc_title = $marc_title.", ".$marc_edition; } + + // Task 849, strip all trailing comma/semicolon/colon from title. + // Space is needed below as there is one at the end of $marc_title + return preg_replace('/[,;: ]+$/', '', $marc_title); +} + +function marc_author($rec) { + $marc_author_100 = $rec[marc_key_search($rec,"100","a")][1]; + $marc_author_100 = trim(preg_replace("/,$/", "", $marc_author_100)); + + if (empty($marc_author_100)) { + $marc_author_700 = $rec[marc_key_search($rec,"700","a")][1]; + $marc_author_700 = trim(preg_replace("/,$/", "", $marc_author_700)); + } + + if (empty($marc_author_100) && empty($marc_author_700)) { + $marc_author_710 = $rec[marc_key_search($rec,"710","a")][1]; + $marc_author_710 = trim($marc_author_710); + } + + if (empty($marc_author_100) && empty($marc_author_700)) { + $marc_author = $marc_author_710; + } elseif (empty($marc_author_100) && isset($marc_author_700)) { + $marc_author = $marc_author_700; + } else { + $marc_author = $marc_author_100; + } + + return $marc_author; +} + +function marc_lccn($rec) { + $marc_lccn = $rec[marc_key_search($rec,"010","a")][1]; + $marc_lccn = trim($marc_lccn); + return $marc_lccn; +} + +function marc_isbn($rec) { + $marc_isbn = $rec[marc_key_search($rec,"020","a")][1]; + $marc_isbn = trim(substr($marc_isbn, 0, 10)); + return $marc_isbn; +} + +function marc_pages($rec) { + $marc_pages = $rec[marc_key_search($rec,"300","a")][1]; + $marc_pages = trim(preg_replace("/:$/", "", $marc_pages)); + return $marc_pages; +} + +function marc_date($rec) { + $marc_date = $rec[marc_key_search($rec,"260","c")][1]; + $marc_date = trim(preg_replace("/.$/", "", $marc_date)); + return $marc_date; +} + +function marc_language($rec) { + $marc_008 = $rec[marc_key_search($rec,"008","")][1]; + $marc_language = substr($marc_008, 35, 3); + $marc_language = convert_short_lang($marc_language); + return $marc_language; +} + +function marc_literary_form($rec) { + global $literary_form_array; + $marc_008 = $rec[marc_key_search($rec,"008","")][1]; + $marc_literary_form = substr($marc_008, 33, 1); + $marc_literary_form = $literary_form_array[$marc_literary_form]; + return $marc_literary_form; +} + +function marc_subject($rec) { + $i = 0; + $marc_subject = ""; + + while ($i < count($rec)) { + if (preg_match("/^\(3,650\)\(3,([^)]*)\)\(3,a\)$/", $rec[$i][0])) { + $marc_subject .= " ".trim($rec[$i][1]).","; + } + $i++; + } + + $marc_subject = trim(preg_replace("/,$/", "", $marc_subject)); + return $marc_subject; +} + +function marc_description($rec) { + $marc_description = $rec[marc_key_search($rec,"520","a")][1]; + $marc_description = trim(preg_replace("/:$/", "", $marc_description)); + return $marc_description; +} + +function marc_publisher($rec) { + $marc_publisher_name = $rec[marc_key_search($rec,"260","b")][1]; + $marc_publisher_name = trim(preg_replace("/,$/", "", $marc_publisher_name)); + $marc_publisher_date = $rec[marc_key_search($rec,"260","c")][1]; + $marc_publisher_date = trim(preg_replace("/.$/", "", $marc_publisher_date)); + + if (isset($marc_publisher_name) && isset($marc_publisher_date)) { + $marc_publisher = $marc_publisher_name.", ".$marc_publisher_date; + } else { + $marc_publisher = $marc_publisher_name; + } + + return $marc_publisher; +} + +function convert_short_lang($marc_language) { + global $lang_list; + $totalLanguages = count($lang_list); + $i = 0; + while ($i <= $totalLanguages) { + if ((substr($lang_list[$i]["lang_code"], 0, 3) == $marc_language) || (substr($lang_list[$i]["lang_code"], 4, 3) == $marc_language)) { + $marc_language = $lang_list[$i]["lang_name"]; + break; + } + $i++; + } + return $marc_language; +} + +function create_dc_xml_oai($projectid, $scannercredit, $genre, $language, $author, $title, $rec) { + $filename = $GLOBALS['projects_dir']."/$projectid/dc.xml"; + + if (!file_exists($filename)) { + touch($filename); + } + + $result = mysql_query("SELECT real_name FROM users WHERE username = '".$GLOBALS['pguser']."'"); + $createdby = "Produced by ".mysql_result($result, 0, "real_name").", "; + if (!empty($scannercredit) && $scannercredit != $GLOBALS['pguser']) { + $result = mysql_query("SELECT real_name FROM users WHERE username = '$scannercredit'"); + $createdby .= mysql_result($result, 0, "real_name").", "; + } + $createdby .= " Simple Simon and the Online Distributed Proofreading Team."; + + $xmlpage = "<"."?"."xml version=\"1.0\" encoding=\"{$GLOBALS['charset']}\" ?"."> + + $title + $author + ".marc_subject($rec)." + ".marc_description($rec)." + Project Gutenberg Canada + $createdby + ".marc_date($rec)." + $genre + XML + {$GLOBALS['code_url']}/project.php?id=$projectid + LCCN: ".marc_lccn($rec)." + $language + http://www.pgdpcanada.net/agreement.php + "; + + $fp = fopen($filename, "w"); + fwrite($fp, $xmlpage); + fclose($fp); +} + +function update_marc_array($rec) { + global $literary_form_array, $lang_list; + + //Update the Name of Work + if (!empty($_POST['nameofwork'])) { $rec[marc_key_search($rec,"245","a")][1] = $_POST['nameofwork']; } + + //Update the Authors Name + if (!empty($_POST['authorsname'])) { + if (!empty($rec[marc_key_search($rec,"100","a")][1]) && $author_set != 1) { + $rec[marc_key_search($rec,"100","a")][1] = $_POST['authorsname']; + $author_set = 1; + } + if (!empty($rec[marc_key_search($rec,"700","a")][1]) && $author_set != 1) { + $rec[marc_key_search($rec,"700","a")][1] = $_POST['authorsname']; + $author_set = 1; + } + if (!empty($rec[marc_key_search($rec,"710","a")][1]) && $author_set != 1) { + $rec[marc_key_search($rec,"710","a")][1] = $_POST['authorsname']; + $author_set = 1; + } + } + + //Update the Primary Language + for ($i=0;$i $tag_value) { + if (strlen($tag_value[0]) == 7) { + $i = 1; + $length = 0; + $directory .= substr($tag_value[0], 3, 3); + + while (substr($rec[$tag+$i][0], 0, 7) == $tag_value[0] && strlen($rec[$tag+$i][0]) != 7) { + if (count($rec[$tag+$i]) == 1) { + if (strlen($rec[$tag+$i][0]) == 12) { $length++; } else { $length = $length + 2; } + } elseif (count($rec[$tag+$i]) == 2) { + if (!preg_match("/^\(3,...\)\(3,@\)$/", $rec[$tag+$i][0])) { $length = $length + 2; } + } + $length = $length + strlen($rec[$tag+$i][1]); + $i++; + } + + if (strlen($directory) == 3) { $start = "00000"; } else { $start = (substr($directory, -12, 4) + substr($directory, -8, 5)); } + + $start = str_pad($start, 5, "0", STR_PAD_LEFT); + $length = str_pad($length+1, 4, "0", STR_PAD_LEFT); + $directory .= $length.$start; + + foreach ($rec as $field => $field_value) { + if (preg_match("/^\(3,".substr($tag_value[0], 3, 3)."\)\(3,[012[:space:]]+\)$/", $field_value[0]) && !in_array(substr($tag_value[0], 3, 3), $stack)) { + $data .= "\x1E".substr($field_value[0], 10, 2); + } + if (preg_match("/^\(3,".substr($tag_value[0], 3, 3)."\)\(3,[012[:space:]]+\)\(3,.\)$/", $field_value[0]) && !in_array(substr($tag_value[0], 3, 3), $stack)) { + $data .= "\x1F".substr($field_value[0], -2, 1).$field_value[1]; + } + if (preg_match("/^\(3,".substr($tag_value[0], 3, 3)."\)\(3,@\)$/", $field_value[0])) { + $data .= "\x1E".$field_value[1]; + } + } + array_push($stack, substr($tag_value[0], 3, 3)); + } + } + + $data .= "\x1E\x1D"; + $leader = str_pad((strlen($directory)+strlen($data)+24), 5, "0", STR_PAD_LEFT)."cam 22".str_pad((strlen($directory)+25), 5, "0", STR_PAD_LEFT)." u 4500"; + $raw_marc = $leader.$directory.$data; + return $raw_marc; +} +?> diff --git a/c/pinc/maybe_mail.inc b/c/pinc/maybe_mail.inc new file mode 100644 index 0000000..359ab53 --- /dev/null +++ b/c/pinc/maybe_mail.inc @@ -0,0 +1,9 @@ +" ); +} diff --git a/c/pinc/mentorbanner.inc b/c/pinc/mentorbanner.inc new file mode 100644 index 0000000..8b3acd7 --- /dev/null +++ b/c/pinc/mentorbanner.inc @@ -0,0 +1,36 @@ +SqlOneValue(" + SELECT + MAX(DATEDIFF(CURRENT_DATE(), FROM_UNIXTIME(modifieddate))) days_ago + FROM projects + WHERE difficulty = 'beginner' + AND LANGUAGE = 'English' + AND state = 'P2.proj_avail'"); + + switch ($oldest) { + case 0: + return; + case 1: + case 2: + $font_boost = "1.1em"; + $font_col = '#339933'; + break; + case 3: + case 4: + $font_boost = "1.2em"; + $font_col = "#FF6600"; + break; + default: + $font_boost = "1.3em"; + $font_col = "#FF0000"; + break; + } + + echo "
    " + . _("Oldest English MENTORS ONLY book in P2 is $oldest days old.") + . "
    +
    \n"; +} diff --git a/c/pinc/metarefresh.inc b/c/pinc/metarefresh.inc new file mode 100644 index 0000000..26a7d2e --- /dev/null +++ b/c/pinc/metarefresh.inc @@ -0,0 +1,43 @@ +$title\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo $body, "\n"; + +/* + if ($testing) { + echo "\n
    \n"; + echo _("Normally, you would be directed to the next page in $seconds seconds. + However, as we are in testing mode, this has been increased to $sec seconds. + If you don't want to wait that long, + or if you want this page inserted into your browser history, + click here."); + echo ""; + } +*/ + echo ""; +} +?> diff --git a/c/pinc/misc.inc b/c/pinc/misc.inc new file mode 100644 index 0000000..db61942 --- /dev/null +++ b/c/pinc/misc.inc @@ -0,0 +1,240 @@ +0 strings, return an array +// [$left_common, $middles, $right_common] +// where +// $left_common is the maximal common prefix of the strings; +// $right_common is the maximal common suffix, subject to the constraint that it +// cannot include characters covered by the common prefix; and +// $middles is an array of N strings, each being that part of the corresponding +// input string that is not covered by the common prefix and suffix. +// +// That is, +// $strings[$i] == $left_common . $middles[$i] . $right_common +// for all $i. +function factor_strings( $strings ) { + assert( count($strings) > 0 ); + + // Find the shortest string + $str_with_minlen = NULL; + $minlen = NULL; + foreach ( $strings as $string ) { + $len = strlen($string); + if (is_null($minlen) || $len < $minlen) { + $minlen = $len; + $str_with_minlen = $string; + } + } + + $base = $str_with_minlen; + + // -------------------------------------------------------------- + + for ( $L = 0; ; $L++ ) { + // Invariant: all strings match in their first $L characters. + + if ($L == $minlen) break; + + // Do they match in their first $L+1 characters? + // Examine the ($L+1)th character, i.e. the one at index $L. + + $c = substr( $base, $L, 1 ); + foreach ( $strings as $string ) { + if ( substr( $string, $L, 1 ) == $c ) { + // good so far + } + else { + // mismatch. + // The invariant does not hold for $L+1. + // So $L is the maximum value that satisfies the invariant. + break 2; + } + } + // No mismatch found for any string for index $L. + // So the invariant holds for $L+1. + } + $left_match_length = $L; + + // -------------------------------------------------------------- + + for ( $R = 0; ; $R++ ) { + // Invariant: all strings match in their last $R characters. + + if ( $left_match_length + $R == $minlen ) + break; + + // Do they match in their last $R+1 characters? + // Examine the ($R+1)th-last character, i.e., the one at index -($R+1). + // e.g. when $R == 0, examine the last character, at index -1 + // when $R == 1, examine the 2nd-last character, at index -2 + + $c = substr($base,-($R+1),1); + + foreach ( $strings as $string ) { + if ( substr( $string, -($R+1), 1 ) != $c ) { + // mismatch. + // The invariant does not hold for $R+1. + // So $R is the maximum value that satisfies the invariant. + break 2; + } + } + // No mismatch found for any string at that index. + // So the invariant holds for $R+1. + } + $right_match_length = $R; + + // -------------------------------------------------------------- + + $left_common = NULL; + $right_common = NULL; + $middles = array(); + + foreach ( $strings as $string ) { + assert( $left_match_length >= 0 ); + assert( $right_match_length >= 0 ); + assert( $left_match_length + $right_match_length <= strlen($string) ); + + if ( $left_match_length == strlen($string) ) { + // substr() misbehaves + $left = $string; + $middle = ''; + $right = ''; + } + else { + $left = substr( $string, 0, $left_match_length ); + + if ( $right_match_length == 0 ) { + $middle = substr( $string, $left_match_length ); + $right = ''; + } + else { + $middle = substr( $string, $left_match_length, -$right_match_length ); + $right = substr( $string, -$right_match_length ); + } + } + + if ( is_null($left_common) ) { + $left_common = $left; + $right_common = $right; + } + else { + assert( $left == $left_common ); + assert( $right == $right_common ); + } + + $middles[] = $middle; + } + + return array( $left_common, $middles, $right_common ); +} + +// vim: sw=4 ts=4 expandtab +?> diff --git a/c/pinc/month_chart.php b/c/pinc/month_chart.php new file mode 100644 index 0000000..28f8c34 --- /dev/null +++ b/c/pinc/month_chart.php @@ -0,0 +1,99 @@ + + " . makeMonthlyChart($phase). " + \n"; +} + +function makeMonthlyChart($phase) { + global $dpdb; + $psql = monthly_sql($phase); + $obj = $dpdb->SqlObjects($psql); + $data = array(); + foreach($obj as $o) { + $moyr = "{$o->mo}/{$o->yr}"; + $data[$moyr] = $o->pages; + } + return echoMonthlyChart($phase, $data, "div_monthly_{$phase}"); +} + +function echoMonthlyChart($phase, $data, $div_id) { + $str = " + + + "; + return $str; +} + +function monthly_sql($phase) { + if($phase == "All") { + return " + SELECT + MONTH(FROM_UNIXTIME(count_time)) mo + , YEAR(FROM_UNIXTIME(count_time)) yr + , SUM(page_count) pages + FROM + user_round_pages + WHERE count_time < UNIX_TIMESTAMP(CAST(DATE_FORMAT(CURRENT_DATE() ,'%Y-%m-01') as DATE)) + GROUP BY + MONTH(FROM_UNIXTIME(count_time)), + YEAR(FROM_UNIXTIME(count_time)) + ORDER BY + YEAR(FROM_UNIXTIME(count_time)), + MONTH(FROM_UNIXTIME(count_time))"; + } + else { + return " + SELECT + MONTH(FROM_UNIXTIME(count_time)) mo + , YEAR(FROM_UNIXTIME(count_time)) yr + , SUM(page_count) pages + FROM + user_round_pages + WHERE round_id = '$phase' + AND count_time < UNIX_TIMESTAMP(CAST(DATE_FORMAT(CURRENT_DATE() ,'%Y-%m-01') as DATE)) + GROUP BY + round_id, + MONTH(FROM_UNIXTIME(count_time)), + YEAR(FROM_UNIXTIME(count_time)) + ORDER BY + round_id, + YEAR(FROM_UNIXTIME(count_time)), + MONTH(FROM_UNIXTIME(count_time))"; + } +} diff --git a/c/pinc/new_user_mails.inc b/c/pinc/new_user_mails.inc new file mode 100644 index 0000000..deffe0c --- /dev/null +++ b/c/pinc/new_user_mails.inc @@ -0,0 +1,218 @@ +\nX-Sender: <$general_help_email_addr>\nX-Mailer: PHP\nReturn-Path: <$general_help_email_addr>\n"); +} + +function maybe_welcome_mail($email, $real_name, $username) { + + global $PG_home_url, $code_url, $reset_password_url, $auto_email_addr; + + $welcome = _("Welcome to the Distributed Proofreaders' Canada Site!"); + + maybe_mail($email, $welcome, " + +Hello $real_name, + +This is an autogenerated message, containing introductory information +about Distributed Proofreaders Canada. + +We want to first thank you for joining DP Canada. That is the +first step in helping us proofread books for Project Gutenberg Canada +<$PG_home_url>. + +To make sure you will be able to access and use our web site +properly, please check that your browser settings are as follows: + +- javascript enabled +- cookies accepted (at least from us at $site_url) +- popup windows allowed (at least from us at $site_url) + +Also, please ensure your PC clock is set to the correct date +and time. + +As a new user, we recommend you read over our main page +<$code_url/> for an overview of the site, +a selection of the works that we are working on, along +with the books that have been completed through the site. +The Beginning Proofreaders FAQ <$code_url/faq/ProoferFAQ.php> +also provides a nice overview of the site. The " +. link_to_proofing_guidelines("Proofreading Guidelines") ." +cover most proofreading +questions, and it is worth browsing through early on, but +don't feel you have to memorize everything in it immediately - +it really comes into its own as a detailed reference whenever +you are unsure of how to handle something. You may find that the +shorter, printable Handy Guide <$code_url/faq/proofing_summary.pdf> +offers a useful introduction to the most common of our standards, +and it may be worth keeping a printed copy by the computer (or an +online copy open in another window) as you proofread. + +Once you understand the work being done through this site, +the best thing to do is get started! Here's a step-by-step +process once you log in: + +- When you log in you are taken to the Activity Hub. Take + special note of the navigational bar at the top of the screen. + It appears on many pages on site, and towards the right contains + many useful links, such as to our FAQs (help), the discussion + Forums, your personal Inbox, etc. Next, scroll down and follow + the \"Proofreading Round 1\" link to see a listing of the books + currently available in first round. Each book on the site goes + through multiple rounds of proofreading. When you first start, + you are only shown the books in the first round. Other rounds + will be available to you later on. + +- Select a book that you would like to read a little bit on. + +- Follow the link for the title you want to work on. This will open + the Project Comments page for this project (book). + +- Among the contents of the Project Comments page may be some + special instructions from the Project Manager. Please read these + carefully as they supersede the Proofreading Guidelines, for that + project. + +- Follow the \"Start Proofreading\" link near the bottom of the page, + this will open the proofreading interface. + +- Compare the text in the text box to what is in the image, making + corrections for differences between the two and any additional + items described in the comments. You can pull the comments back + up by clicking on the link below the text box. + +- Once you are finished with this page, click on either + \"Save as 'Done'\" or \"Save as 'Done' & Proof Next\" + +That is all there is to completing your first page. + +Here are some brief answers to common questions: + +Q: What books should I start on? + +A: You can start on any that look interesting to you. As a new + beginner, you might want to consider a book marked BEGINNERS ONLY, + as these will be given especially close attention by experienced + second round proofreaders who will send you messages containing + feedback on your proofreading if you make any serious errors, via + our on-site messaging system. (Be sure to check your personal Inbox + regularly.) After you've done a few pages of a BEGINNERS ONLY + project, you might want to sample one of the several EASY + projects usually available. (Don't be afraid to try any project; + if you run into a page you decide you'd rather not do, you can + always press the \"Return Page to Round\" button and let someone + else tackle it.) + +Q: I'm not sure how to use the interface or how I should mark + something up. + +A: You can get help for the various buttons on the proofreading interface + by pressing the ? button near the lower right corner. If there's + something in the image you are unsure about, you can mark it with + a [**your comment], which is our special universal signal for the next person + working on the page to pay extra attention to a particular spot + because there is something unusual there. Remember there will be + several other pairs of eyes looking at this page before it gets + posted to Project Gutenberg Canada, so don't feel you are carrying the + whole thing on your shoulders alone - the system is set up so + we can all help each other and back each other up! + + If you have specific questions on a book, you can post a message + in the forum thread reserved for it by following the link + labeled \"Discuss this project\" that appears on the Project + Comments page. Each project has a forum thread of its own; you + can post a question or message via the \"Reply\" button near the + bottom of the forum screen. It's often worthwhile reading through + the discussion on a project even if you don't have a specific + question, just to see what other proofreaders have asked and answered + or warned each other about. (There are also several other forums + dedicated to various phases of our operation. You can reach them + by following the Forums link near the right hand end of the + navigation bar at the top of many of the pages on site. The + General Forum in particular is a great place to get your feet + wet, browse and start to get a sense of the community of + proofreaders here, to make suggestions or to ask general + questions. You can learn a lot just by following some of the + discussions. ***We strongly encourage everyone to participate in + the Forums!***) + + (By the way, when you register on the main site you are automatically + also registered on the site forums, but you will have to log on + to them to access them. You do NOT need to register separately for + the forums - in fact, if you try to, you will receive a \"username + already exists\" error, since the forums will already have your + username recorded from when you registered at the main site!) + +Q: How do I know if I'm doing OK? + +A: If you select a BEGINNERS ONLY project, you are more likely to + receive some feedback. If you are making major errors on any + project someone will let you know. If you want to increase your + chances of receiving some feedback, you can leave a message to + the second round proofreader at the top of the page, in square + brackets [ ] and starting with two *, such as + + [** new proofreader, how am I doing?] + or + [** feedback welcome!] + + It's up to the individual second round proofreader, but many will + respond to such a request. + + +Remember, every page you do helps make these books available to +the world, for free, forever, more rapidly. We hope that you will +continue to use our site, and that you enjoy your time on our site. +We're delighted to have you join us, as each page we proofread is +another small step closer to building the greatest library in history! + +Thanks, + +The Distributed Proofreaders Canada Team + +PS - Your user name, in case you forget, is $username. +If your password doesn't work, go to +<$reset_password_url> +to have it reset. + ", + "From: DPHelp <$general_help_email_addr>\nX-Sender: <$general_help_email_addr>\nX-Mailer: PHP\nReturn-Path: <$general_help_email_addr>\n"); +} +?> diff --git a/c/pinc/page_header.inc b/c/pinc/page_header.inc new file mode 100644 index 0000000..8f71332 --- /dev/null +++ b/c/pinc/page_header.inc @@ -0,0 +1,24 @@ + +
    + $title +
    \n"; + } + else { + echo "

    $title

    \n"; + } +} + +// vim: sw=4 ts=4 expandtab +?> diff --git a/c/pinc/page_table.inc b/c/pinc/page_table.inc new file mode 100644 index 0000000..a2f6e24 --- /dev/null +++ b/c/pinc/page_table.inc @@ -0,0 +1,193 @@ +ProjectId(); + $phaseindex = $project->PhaseIndex(); + $phase = $project->Phase(); + $rows = $dpdb->SqlRows(" + SELECT '$projectid' projectid, + $phaseindex phaseindex, + '$phase' phase, + fileid, + image, + master_text, + round1_text, + round2_text, + round3_text, + round4_text, + round5_text, + round1_user, + round2_user, + round3_user, + round4_user, + round5_user, + FROM_UNIXTIME(round1_time) round1_time, + FROM_UNIXTIME(round2_time) round2_time, + FROM_UNIXTIME(round3_time) round3_time, + FROM_UNIXTIME(round4_time) round4_time, + FROM_UNIXTIME(round5_time) round5_time, + LENGTH(master_text) OCR_text_length, + LENGTH(round1_text) round1_text_length, + LENGTH(round2_text) round2_text_length, + LENGTH(round3_text) round3_text_length, + LENGTH(round4_text) round4_text_length, + LENGTH(round5_text) round5_text_length, + CASE WHEN BINARY master_text = BINARY round1_text + THEN 0 ELSE 1 END AS is_diff_1, + CASE WHEN BINARY round1_text = BINARY round2_text + THEN 0 ELSE 1 END AS is_diff_2, + CASE WHEN BINARY round2_text = BINARY round3_text + THEN 0 ELSE 1 END AS is_diff_3, + CASE WHEN BINARY round3_text = BINARY round4_text + THEN 0 ELSE 1 END AS is_diff_4, + CASE WHEN BINARY round4_text = BINARY round5_text + THEN 0 ELSE 1 END AS is_diff_5, + state + FROM $projectid + ORDER BY fileid"); + $tbl = new DpTable(); + + if($project->UserMayManage()) { + $tbl->AddCaption(null, 4); // leave one for the rownumber? + $tbl->AddColumn(chk_caption(), null, "rowchkbox", "width: 4em"); + } + else { + $tbl->AddCaption(null, 2); + } + + $tbl->AddCaption(null, 4); // leave one for the rownumber? + $tbl->AddColumn("^Image", "fileid", "eimage"); + $tbl->AddColumn(">Text", "textlength_m", "mtext"); + $tbl->AddColumn("^State", "state", "estate", "w4em"); + + if($phaseindex > 0) { + $tbl->AddCaption("^".$phaseindex, 4); + + $tbl->AddColumn("^Diff?", "is_diff_1", "ediff"); + $tbl->AddColumn("^Date", "round1_time", "etime"); + $tbl->AddColumn("^User", "round1_user", "euser"); + $tbl->AddColumn("^Text", "round1", "etext"); + } + if($phaseindex > 1) { + $tbl->AddCaption("^".$phaseindex, 4); + + $tbl->AddColumn("^Diff", "is_diff_2", "ediff"); + $tbl->AddColumn("^Date", "round2_time", "etime"); + $tbl->AddColumn("^User", "round2_user", "euser"); + $tbl->AddColumn("^Text", "round2", "etext"); + } + if($phaseindex > 2) { + $tbl->AddCaption("^".$phaseindex, 4); + + $tbl->AddColumn("^Diff", "is_diff_3", "ediff"); + $tbl->AddColumn("^Date", "round3_time", "etime"); + $tbl->AddColumn("^User", "round3_user", "euser"); + $tbl->AddColumn("^Text", "round3", "etext"); + } + if($phaseindex > 3) { + $tbl->AddCaption("^".$phaseindex, 4); + + $tbl->AddColumn("^Diff", "is_diff_4", "ediff"); + $tbl->AddColumn("^Date", "round4_time", "etime"); + $tbl->AddColumn("^User", "round4_user", "euser"); + $tbl->AddColumn("^Text", "round4", "etext"); + } + if($phaseindex > 4) { + $tbl->AddCaption("^".$phaseindex, 3); + + $tbl->AddColumn("^Date", "round5_time", "etime"); + $tbl->AddColumn("^User", "round5_user", "euser"); + $tbl->AddColumn("^Text", "round4", "etext"); + } + $tbl->AddColumn("^Clear", "fileid", "eclear"); + $tbl->AddColumn("^Edit", "fileid", "eedit"); + $tbl->AddColumn("^Bad
    Fix", "fileid", "efix"); + $tbl->AddColumn("^Delete", "fileid", "edelete"); + + $tbl->SetRows($rows); + $tbl->EchoTableNumbered(); +} + +function chk_caption() { + return "^All
    "; +} +function rowchkbox($row) { + $name = 'imagefile['.$row['image'].']'; + return ""; +} +function eimage($pagename, $row) { + $projectid = $row['projectid']; + $imagefile = $row['image']; + + return $pagename != "" + ? link_to_view_image($projectid, $pagename, $pagename, true) + : "$imagefile"; +} + +function enumber($num, $row) { + $projectid = $row['projectid']; + $pagename = $row['fileid']; + return link_to_page_text($projectid, $pagename, number_format($num), true); +} + +function mtext($size, $row) { + $projectid = $row["projectid"]; + $pagename = $row["fileid"]; + $phase = "OCR"; + return link_to_page_text($projectid, $pagename, $phase, $size, true); +} + +function etext($pfx, $row) { + global $User; + $projectid = $row["projectid"]; + $pagename = $row["fileid"]; + $phase = $row["phase"]; + $userval = $row["{$pfx}_user"]; + $size = $row["{$pfx}_text_length"]; + if($userval == $User->Username()) { + return "
    " + .link_to_page_text($projectid, $pagename, $phase, $size, true) + ."
    \n"; + } + return link_to_page_text($projectid, $pagename, $phase, $size, true); +} +function estate($state) { + return preg_replace("/^.*_/", "", $state); +} +function ediff($pagename, $row) { + $projectid = $row["projectid"]; + $phase = $row["phase"]; + return link_to_diff($projectid, $pagename, $phase, "diff", true); +} +function etime($time) { + return $time == 0 ? "" : $time; +} +function euser($proofer) { + global $User; + $username = $User->Username(); + if($proofer == "") { + return ""; + } + return $proofer == $username + ? "
    $proofer
    " + : link_to_pm($proofer, $proofer, true); +} + +function eclear($pagename) { + return "\n"; +} +function eedit($pagename, $row) { + $projectid = $row["projectid"]; + return link_to_proof_page($projectid, $pagename, "Edit", true); +} +function efix($pagename, $row) { + $projectid = $row["projectid"]; + return link_to_fix($projectid, $pagename, true); +} +function edelete($pagename) { + return "\n"; +} + diff --git a/c/pinc/page_tally.inc b/c/pinc/page_tally.inc new file mode 100644 index 0000000..87e6bf4 --- /dev/null +++ b/c/pinc/page_tally.inc @@ -0,0 +1,395 @@ +id] = + sprintf( _('Pages saved-as-done in round %s'), $round->id ); +} + +// ----------------------------------------------------------------------------- + +// The following variables assume that the site has been configured with an +// "Entry-Level Round" (ELR): a single round where new users start out and +// become familiar with the site. The page-tallies from this round are +// distinguished from others in that they are (deemed to be) a fair indicator +// of the user's experience. + +// This assignment particularly assumes that the ELR is the first round +$ELR_round = get_Round_for_round_number(1); + +$users_ELR_page_tallyboard = new TallyBoard( $ELR_round->id, 'U' ); +$teams_ELR_page_tallyboard = new TallyBoard( $ELR_round->id, 'T' ); + +// See TallyBoard.inc for explanation of these two strings: +// +list($joined_with_user_ELR_page_tallies,$user_ELR_page_tally_column) = + $users_ELR_page_tallyboard->get_sql_joinery_for_current_tallies( 'u_id' ); + +// ----------------------------------------------------------------------------- + +/* +// Add $amount to the user's page tally, +// and to the page tally of each team that the user currently belongs to. +function page_tallies_add( $tally_name, $username, $amount ) { + // get the user's u_id, and the teams that he/she belongs to + $result = mysql_query(" + SELECT u_id, team_1, team_2, team_3 + FROM users + WHERE username = '$username'"); + list($u_id, $team_1, $team_2, $team_3) = mysql_fetch_row($result); + + // update page tally for user + $user_tallyboard = new TallyBoard( $tally_name, 'U' ); + $user_tallyboard->add_to_tally( $u_id, $amount ); + + // update page tally for site + $site_tallyboard = new TallyBoard( $tally_name, 'S' ); + $site_tallyboard->add_to_tally( 1, $amount ); + + // update page tally for each team + $team_tallyboard = new TallyBoard( $tally_name, 'T' ); + // (The 'array_unique' shouldn't be necessary, but just in case.) + foreach (array_unique(array($team_1, $team_2, $team_3)) as $team_id) { + if ( $team_id != 0 ) { + $team_tallyboard->add_to_tally( $team_id, $amount ); + } + } +} +*/ + +// ----------------------------------------------------------------------------- + +// Not actually tally-specific, but that's all it's used for. +/* +function get_daily_average( $start_time, $total ) { + $now = time(); + $seconds_since_start = $now - $start_time; + $days_since_start = $seconds_since_start / 86400; + return $total / $days_since_start; +} +*/ + +// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + +// Return the user's page tally for the Entry-Level Round. +/* +function user_get_ELR_page_tally( $username ) { + global $joined_with_user_ELR_page_tallies, $user_ELR_page_tally_column; + + $res = mysql_query(" + SELECT $user_ELR_page_tally_column + FROM users $joined_with_user_ELR_page_tallies + WHERE username='$username'") or die(mysql_error()); + + if ( mysql_num_rows($res) == 0 ) { + // No row matched username='$username'. + // This probably shouldn't happen. + return 0; + } + + return mysql_result($res,0); +} +*/ + +// ----------------------------------------------------------------------------- + +/* +// +// $radius is the (maximum) number of neighbors (on each side) to include in +// the neighborhood. (It will include fewer that the maximum iff the target +// user is within $radius of the corresponding end of the ranked list.) +// +// Return the page-tally neighborhood of $username. +// This is an array: +// The keys are integers from the range [-$radius, +$radius], +// indicating a user's position relative to the target user (w.r.t. page tally). +// (So key=0 refers to the target user.) +// For a given key, the corresponding value is a PageTally_Neighbor object +// supplying various information about the page-tally neighbor. +function user_get_page_tally_neighborhood( $tally_name, $username, $radius ) { + $result = mysql_query(" + SELECT u_id FROM users + WHERE username='$username'"); + if ( mysql_num_rows($result) == 0 ) { + // The target user does not appear in the 'users' table. + // This shouldn't ever happen. + die( "User '$username' does not appear in the 'users' table." ); + } + else if ( mysql_num_rows($result) > 1 ) { + // This shouldn't ever happen either. + die( "username='$username' matched more than one row in 'users' table." ); + } + list($u_id) = mysql_fetch_row($result); + + $tallyboard = new TallyBoard( $tally_name, 'U' ); + $nb = $tallyboard->get_neighborhood( + $u_id, $radius, + 'users', + 'u_id', + 'username, u_privacy, date_created, u_id', + 'current_tally', + 'current_rank'); + + $neighbors = array(); + foreach ( $nb as $rel_posn => $row ) { + if ( should_anonymize( $row['username'], $row['u_privacy'] ) ) { + $neighbor_is_anonymized = TRUE; + $neighbor_username = NULL; + $neighbor_date_joined = NULL; + } + else { + $neighbor_is_anonymized = FALSE; + $neighbor_username = $row['username']; + $neighbor_date_joined = $row['date_created']; + } + + $neighbors[$rel_posn] = + new PageTally_Neighbor( + $tallyboard, + $neighbor_is_anonymized, + $neighbor_username, + $neighbor_date_joined, + $row['u_id'], + $row['current_tally'], + $row['current_rank']); + } + + return $neighbors; +} + +class RoundNeighbor +{ + private $_username; + private $_count; + private $_rank; + private $_user; + + function __construct($row) { + $this->_username = $row['username']; + $this->_count = $row['page_count']; + $this->_rank = $row['rank']; + $this->_user = new DpUser($this->_username); + } + + public function PageCount() { + return $this->_count; + } + + public function Rank() { + return $this->_rank; + } + + public function Username() { + return $this->_username; + } + public function PrivateUsername() { + return $this->_user->PrivateUsername(); + } + public function IsAnonymous() { + return $this->_user->Privacy() > 0; + } + public function DateCreatedInt() { + return $this->_user->DateCreatedInt(); + } + public function AgeDays() { + return $this->_user->AgeDays(); + } +} + +class PageTally_Neighbor +{ + function __construct( $tallyboard, $is_anonymized, $username, $date_joined, $u_id, $tally, $rank ) { + $this->tallyboard = $tallyboard; + $this->is_anonymized = $is_anonymized; + $this->username = $username; + $this->date_joined = $date_joined; + $this->u_id = $u_id; + $this->current_page_tally = $tally; + $this->current_page_tally_rank = $rank; + } + + function is_anonymized() { return $this->is_anonymized; } + function get_username() { return $this->username; } + function get_date_joined() { return $this->date_joined; } + function get_u_id() { return $this->u_id; } + public function get_current_page_tally() { + return $this->current_page_tally; + } + public function get_current_page_tally_rank() { + return $this->current_page_tally_rank; + } +} + +// ----------------------------------------------------------------------------- + +// Should we anonymize information about the given user? +function should_anonymize( $username, $user_privacy_setting ) { + return !can_reveal_details_about( $username, $user_privacy_setting ); +} +*/ + +// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + +// Return an object whose attributes are various useful statistics re +// the site page tally: +// curr_day_{goal,actual} +// prev_day_{goal,actual} +// curr_month_{goal,actual} + +function get_site_page_round_summary( $roundid) { + return get_site_page_tally_summary( $roundid); +} + +function get_site_page_tally_summary( $roundid ) { + global $dpdb; + $site_stats = new StdClass; + + // Goals + +// $site_stats->curr_day_goal = $dpdb->SqlOneValue(" + $row = $dpdb->SqlOneRow(" + SELECT pg.goal, + pg1.goal ygoal + FROM phase_goals pg + JOIN phase_goals pg1 + ON pg.phase = pg1.phase + AND pg1.goal_date = DATE_ADD(pg.goal_date, INTERVAL -1 DAY) + WHERE pg.phase = '$roundid' + AND pg.goal_date = CURRENT_DATE()"); + $site_stats->curr_day_goal = $row["goal"]; + $site_stats->prev_day_goal = $row["goal"]; + +// $site_stats->prev_day_goal = $dpdb->SqlOneValue(" +// SELECT goal FROM site_tally_goals +// WHERE tally_name = '$roundid' +// AND date = DATE_SUB(CURRENT_DATE(), INTERVAL 1 DAY)" ); + // get_site_tally_goal_summed( + // $tally_name, + // "date = (CURRENT_DATE - INTERVAL 1 DAY)" ); + + $site_stats->curr_month_goal = $dpdb->SqlOneValue(" + SELECT SUM(goal) FROM phase_goals + WHERE phase = '$roundid' + AND goal_date >= DATE(DATE_FORMAT(NOW() ,'%Y-%m-01')) + AND goal_date < DATE_ADD(DATE(DATE_FORMAT(NOW() ,'%Y-%m-01')), INTERVAL 1 MONTH)"); + // get_site_tally_goal_summed( + // $tally_name, + // "YEAR(date) = YEAR(CURRENT_DATE) AND + // MONTH(date) = MONTH(CURRENT_DATE)" ); + + + // Actuals + + // $tallyboard = new TallyBoard( $tally_name, 'S' ); + +// $holder_id = 1; + + $site_stats->curr_day_actual = $dpdb->SqlOneValue(" + SELECT COUNT(1) FROM page_events_save + WHERE round_id = '$roundid' + AND timestamp >= UNIX_TIMESTAMP(CURRENT_DATE())"); + + $site_stats->prev_day_actual = $dpdb->SqlOneValue(" + SELECT COUNT(1) FROM page_events_save + WHERE round_id = '$roundid' + AND timestamp >= UNIX_TIMESTAMP(DATE_SUB(CURRENT_DATE(), INTERVAL 1 day)) + AND timestamp < UNIX_TIMESTAMP(CURRENT_DATE())"); + + $site_stats->curr_month_actual = $dpdb->SqlOneValue(" + SELECT SUM(pagecount) + FROM + ( SELECT SUM(urp.page_count) pagecount + FROM user_round_pages urp + WHERE round_id = '$roundid' + AND count_time >= UNIX_TIMESTAMP(DATE(DATE_FORMAT(NOW() ,'%Y-%m-01'))) + UNION ALL + SELECT COUNT(1) pagecount + FROM page_events_save + WHERE round_id = '$roundid' + AND TIMESTAMP > UNIX_TIMESTAMP(CURRENT_DATE()) + ) a"); + + return $site_stats; +} + +/* +function get_site_count_goal_summed( $roundid, $date_condition ) { + $res = mysql_query(" + SELECT SUM(goal) FROM site_count_goals + WHERE count_name = '$roundid' + AND ($date_condition)") or die(mysql_error()); + return mysql_result($res,0); +} +*/ + +// ----------------------------------------------------------------------------- + +// Return a string containing an SQL 'select' statement +// dealing with site-specific rows from the past_tallies table, +// and corresponding rows from the site_count_goals table. +function select_from_site_past_tallies_and_goals( $tally_name, $select, + $where, $groupby, $orderby, $limit ) { + if (empty($where)) { + $where_addition = ''; + } + else { + $where_addition = + preg_replace( '/^\s*WHERE\s+(.*)$/i', 'AND (\1)', $where ); + } + + $s = " + $select + FROM past_tallies + LEFT JOIN site_tally_goals + ON past_tallies.tally_name = site_tally_goals.tally_name + AND {date} = site_tally_goals.date + WHERE past_tallies.tally_name='$tally_name' + AND holder_type='S' + AND holder_id=1 + $where_addition + $groupby + $orderby + $limit"; + + $date_expr = "FROM_UNIXTIME(past_tallies.timestamp-1,'%Y-%m-%d')"; + $ym_expr = "FROM_UNIXTIME(past_tallies.timestamp-1,'%Y-%m')"; + $y_expr = "FROM_UNIXTIME(past_tallies.timestamp-1,'%Y')"; + + $is_curr_month_expr = "$ym_expr = DATE_FORMAT(NOW(),'%Y-%m')"; + $is_curr_year_expr = "$y_expr = YEAR(NOW())"; + + $s = preg_replace( '/{date}/', $date_expr, $s ); + $s = preg_replace( '/{year_month}/', $ym_expr, $s ); + $s = preg_replace( '/{is_curr_month}/', $is_curr_month_expr, $s ); + $s = preg_replace( '/{is_curr_year}/', $is_curr_year_expr, $s ); + + return $s; +} + +// vim: sw=4 ts=4 expandtab diff --git a/c/pinc/pg old.inc b/c/pinc/pg old.inc new file mode 100644 index 0000000..c9c8eaf --- /dev/null +++ b/c/pinc/pg old.inc @@ -0,0 +1,44 @@ + element +// that links to the PG catalog page for that text. +{ + $url = get_pg_catalog_url_for_etext( $etext_number ); + + if ( is_null($link_text) ) + { + //MS + $link_text = sprintf( _('PGC etext #%d'), $etext_number ); + } + + return "$link_text"; +} + +// vim: sw=4 ts=4 expandtab +?> diff --git a/c/pinc/pg.inc b/c/pinc/pg.inc new file mode 100644 index 0000000..815b0d2 --- /dev/null +++ b/c/pinc/pg.inc @@ -0,0 +1,44 @@ + element +// that links to the PG catalog page for that text. +{ + $url = get_pg_catalog_url_for_etext( $etext_number ); + + if ( is_null($link_text) ) + { + //MS + $link_text = sprintf( _('FadedPage etext #%d'), $etext_number ); + } + + return "$link_text"; +} + +// vim: sw=4 ts=4 expandtab +?> diff --git a/c/pinc/phases.php b/c/pinc/phases.php new file mode 100644 index 0000000..0e81d27 --- /dev/null +++ b/c/pinc/phases.php @@ -0,0 +1,55 @@ + _('Preparation'), + "description" => _("Images are converted to OCR text, + and both the text and images are checked for completeness and quality.") ); + +$DpPhases["P1"] = array( "name" => _('Proofreading Round 1'), + "description" => _("The text is the output from OCR software. + Compare it carefully with the image.") ); + +$DpPhases["P2"] = array( "name" => _('Proofreading Round 2'), + "description" => _("The texts have been proofread once. + Now carefully compare them with the image again.") ); + +$DpPhases["P3"] = array( "name" => _('Proofreading Round 3'), + "description" => _("The texts have been proofread twice. + Examine them closely for small errors that may have been missed, + paying careful attention to the punctuation.") ); + +$DpPhases["F1"] = array( "name" => _('Formatting Round 1'), + "description" => _("The texts have been proofread. + Now they need to be formatted with markup + (which may in some cases be specific to the project.)") ); + +$DpPhases["F2"] = array( "name" => _('Formatting Round 2'), + "description" => _("The rexts need to be carefully checked to complete any remaining formatting.") ); + +$DpPhases["PP"] = array( "name" => _('Post Processing'), + "description" => _("The texts have completed the rounds, + and now are converted to publication-quality texts.") ); + +$DpPhases["PPV"] = array( "name" => _('PP Verifying'), + "description" => _("A final check to confirm that the project meets DPC and FadedPage standards.") ); + +function PhaseCaption($phase) { + return _("Pages Completed in $phase"); +} + +function NameForPhase($phase) { + global $DpPhases; + return $phase != "" && is_array($DpPhases[$phase]) + ? $DpPhases[$phase]['name'] + : ""; +} + +function DescriptionForPhase($phase) { + global $DpPhases; + return $phase != "" && is_array($DpPhases[$phase]) + ? $DpPhases[$phase]['description'] + : ""; +} + diff --git a/c/pinc/postcomments.inc b/c/pinc/postcomments.inc new file mode 100644 index 0000000..ec531fe --- /dev/null +++ b/c/pinc/postcomments.inc @@ -0,0 +1,20 @@ + . +function get_formatted_postcomments( $projectid ) { + global $dpdb; + $postcomments = $dpdb->SqlOneValue(" + SELECT postcomments FROM projects WHERE projectid='$projectid'"); + + return htmlspecialcharswithnewlines($postcomments); +} + +function htmlspecialcharswithnewlines($string) { + $string = htmlspecialchars($string); + $string = str_replace("\n", "
    ", $string); + return $string; +} + +?> diff --git a/c/pinc/prefs_options.inc b/c/pinc/prefs_options.inc new file mode 100644 index 0000000..7ba2a98 --- /dev/null +++ b/c/pinc/prefs_options.inc @@ -0,0 +1,50 @@ + BROWSER_DEFAULT_STR, + 1 => '8pt', 2 => '9pt', 3 => '10pt', 4 => '11pt', 5 => '12pt', 6 => '13pt', + 7 => '14pt', 8 => '15pt', 9 => '16pt', 10 => '18pt', 11 => '20pt'); + +$u_radius = array('0', '2', '4', '6', '8', '10', '12', '14', '16', '18', '20'); + +$u_intlang_tmp = installed_langs(); +$u_intlang_options[""] = BROWSER_DEFAULT_STR; +foreach($u_intlang_tmp as $k => $v) { + $u_intlang_options[$v] = bilingual_name($v); +} + +$i_pm = array(_("All Projects"), _("Active Projects"), _("Search Page")); + +$i_stats = array(_("Public"), _("Anonymous"), _("Private")); +define('PRIVACY_PUBLIC', 0); +define('PRIVACY_ANONYMOUS', 1); +define('PRIVACY_PRIVATE', 2); +// See ../faq/pophelp/prefs/set_privacy.html +// for definitions of these privacy categories. +?> diff --git a/c/pinc/privacy.inc b/c/pinc/privacy.inc new file mode 100644 index 0000000..82c6445 --- /dev/null +++ b/c/pinc/privacy.inc @@ -0,0 +1,30 @@ + diff --git a/c/pinc/project_edit.inc b/c/pinc/project_edit.inc new file mode 100644 index 0000000..a938181 --- /dev/null +++ b/c/pinc/project_edit.inc @@ -0,0 +1,80 @@ +SqlOneValue(" + SELECT username FROM projects WHERE projectid = '$projectid'"); + if ($User->IsProjectManager()) { + // The current user is the project manager for the project. + return USER_CAN_EDIT_PROJECT; + } + + if ( user_is_a_sitemanager() || user_is_proj_facilitator() ) { + return USER_CAN_EDIT_PROJECT; + } + + return USER_CANNOT_EDIT_PROJECT; +} + +// Politely abort if the current user ($pguser) +// is not allowed to edit the specified project +function abort_if_cant_edit_project( $projectid ) { + global $site_manager_email_addr; + + $result = user_can_edit_project($projectid); + + if ( $result == PROJECT_DOES_NOT_EXIST ) { + echo " +

    + "._("There appears to be no such project")." ($projectid). +

    + "._("If this message is an error, contact the")." "._("site manager").". +

    "._("Back").""; + theme( "", "footer" ); + exit; + } + else if ( $result == USER_CANNOT_EDIT_PROJECT ) { + echo " +

    + "._("You are not allowed to change this project")." ($projectid). +

    + "._("If this message is an error, contact the")." "._("site manager").". +

    "._("Back").""; + theme( "", "footer" ); + exit; + } + else if ( $result == USER_CAN_EDIT_PROJECT ) { + return; + } + else { + echo "unexpected return value from user_can_edit_project: '$result'"; + exit; + } +} + +// Can the current user delete a project in the given state? +// (assuming that the current user can edit/manage the project) +function user_can_delete_project_in_state( $project_state ) { + // PM/PF/SA can delete a project when it's new. + // SA can 'delete' a project when it's in any state but already-deleted. + // (There's a difference to what 'deletion' means in the latter case.) + return ( + $project_state == PROJ_NEW + || $project_state != PROJ_DELETE && user_is_a_sitemanager()); +} + +// vim: sw=4 ts=4 expandtab +?> diff --git a/c/pinc/project_events.inc b/c/pinc/project_events.inc new file mode 100644 index 0000000..29bdb08 --- /dev/null +++ b/c/pinc/project_events.inc @@ -0,0 +1,20 @@ +SqlExecute($sql) == 1 ? "" : "Proj log failed" ; +} + +// vim: sw=4 ts=4 expandtab +?> diff --git a/c/pinc/project_states.inc b/c/pinc/project_states.inc new file mode 100644 index 0000000..ab7dadd --- /dev/null +++ b/c/pinc/project_states.inc @@ -0,0 +1,407 @@ + array(), + 'SILVER' => array(), + 'GOLD' => array(), +); + +function declare_project_state( $constant_name, $constant_value, $label, + $forum, $phase, $star_metal ) { + global $PROJECT_STATES_IN_ORDER; + global $project_state_label_; + global $project_state_forum_; + global $project_state_phase_; + global $project_states_for_star_metal_; + + define( $constant_name, $constant_value ); + $PROJECT_STATES_IN_ORDER[] = $constant_value; + $project_state_label_[$constant_value] = $label; + $project_state_forum_[$constant_value] = $forum; + $project_state_phase_[$constant_value] = $phase; + if ($star_metal) + $project_states_for_star_metal_[$star_metal][] = $constant_value; +} + +function project_states_text($state) { + global $project_state_label_; + return array_get( $project_state_label_, $state, '' ); +} + +function get_forum_id_for_project_state($state) { + global $project_state_forum_; + return array_get( $project_state_forum_, $state, -1 ); +} + +function get_phase_containing_project_state($state) { + global $project_state_phase_; + return array_get( $project_state_phase_, $state, 'NONE' ); +} + +// ----------------------------------------------- + +function declare_project_states_for_round( $round_id, $round_name ) { + global $projects_forum_idx; + global $waiting_projects_forum_idx; + + declare_project_state( + "PROJ_{$round_id}_BAD_PROJECT", + "$round_id.proj_bad", + "$round_name: " . _("Bad Project"), + $projects_forum_idx, + 'PAGE_EDITING', ''); + declare_project_state( + "PROJ_{$round_id}_UNAVAILABLE", + "$round_id.proj_unavail", + "$round_name: " . _("Unavailable"), + ($round_id == 'P1' ? $waiting_projects_forum_idx : $projects_forum_idx ), + 'PAGE_EDITING', ''); + declare_project_state( + "PROJ_{$round_id}_WAITING_FOR_RELEASE", + "$round_id.proj_waiting", + "$round_name: " . _("Waiting for Release"), + ($round_id == 'P1' ? $waiting_projects_forum_idx : $projects_forum_idx ), + 'PAGE_EDITING', ''); + declare_project_state( + "PROJ_{$round_id}_AVAILABLE", + "$round_id.proj_avail", + "$round_name: " . _("Available"), + $projects_forum_idx, + 'PAGE_EDITING', + 'BRONZE'); + declare_project_state( + "PROJ_{$round_id}_COMPLETE", + "$round_id.proj_done", + "$round_name: " . _("Completed"), + $projects_forum_idx, + 'PAGE_EDITING', + ''); +} + +// ----------------------------------------------- + +// Note that the order in which these project states are declared +// is the order in which they will be displayed in various contexts +// (via $PROJECT_STATES_IN_ORDER). + + +// PR + + +// for the initial creation of a project +declare_project_state( + "PROJ_NEW", + "project_new", + _("New Project"), + $waiting_projects_forum_idx, + 'NEW', + ''); + +if ($site_supports_metadata) { + declare_project_state( + "PROJ_NEW_WAITING_APPROVAL", + "project_new_waiting_app", + _("Awaiting Approval"), + $waiting_projects_forum_idx, + 'NONE', + ''); + declare_project_state( + "PROJ_NEW_UNAPPROVED", + "project_new_unapp", + _("Unapproved Project"), + $waiting_projects_forum_idx, + 'NONE', + ''); + declare_project_state( + "PROJ_NEW_APPROVED", + "project_new_app", + _("Approved Project"), + $waiting_projects_forum_idx, + 'NONE', + ''); + declare_project_state( + "PROJ_NEW_FILE_UPLOADED", + "project_new_uploaded", + _("Files Uploaded"), + $waiting_projects_forum_idx, + 'NONE', + ''); + declare_project_state( + "PROJ_NEW_METADATA_FIRST", + "project_md_first", + _("Metadata First Round"), + $waiting_projects_forum_idx, + 'NONE', + ''); + declare_project_state( + "PROJ_NEW_METADATA_BAD", + "project_md_bad", + _("Bad Metadata"), + $waiting_projects_forum_idx, + 'NONE', + ''); + declare_project_state( + "PROJ_NEW_METADATA_SECOND", + "project_md_second", + _("Metadata Second Round"), + $waiting_projects_forum_idx, + 'NONE', + ''); + declare_project_state( + "PROJ_NEW_PREPROCESSING", + "project_new_preprocess", + _("Preprocessing"), + $waiting_projects_forum_idx, + 'NONE', + '' + ); + declare_project_state( + "PROJ_NEW_PENDING_PM", + "project_new_pend_pm", + _("Pending Project Manager"), + $waiting_projects_forum_idx, + 'NONE', + ''); +} + + +// PROOF +declare_project_states_for_round( 'P1', _('Proofreading Round 1') ); +declare_project_states_for_round( 'P2', _('Proofreading Round 2') ); +declare_project_states_for_round( 'P3', _('Proofreading Round 3') ); + +// FORMAT +declare_project_states_for_round( 'F1', _('Formatting Round 1') ); +declare_project_states_for_round( 'F2', _('Formatting Round 2') ); + + +// POST +declare_project_state( + "PROJ_POST_FIRST_UNAVAILABLE", + "proj_post_first_unavailable", + _("Unavailable for Post-Processing"), + $pp_projects_forum_idx, + 'PP', + 'SILVER'); +declare_project_state( + "PROJ_POST_FIRST_AVAILABLE", + "proj_post_first_available", + _("Available for Post-Processing"), + $pp_projects_forum_idx, + 'PP', + 'SILVER'); + +declare_project_state( + "PROJ_POST_FIRST_CHECKED_OUT", + "proj_post_first_checked_out", + _("In Post-Processing"), + $pp_projects_forum_idx, + 'PP', + 'SILVER'); + +declare_project_state( + "PROJ_POST_SECOND_AVAILABLE", + "proj_post_second_available", + _("Available for Verifying Post-Processing"), + $pp_projects_forum_idx, + 'PP', + 'SILVER'); + +declare_project_state( + "PROJ_POST_SECOND_CHECKED_OUT", + "proj_post_second_checked_out", + _("Verifying Post-Processing"), + $pp_projects_forum_idx, + 'PP', + 'SILVER'); +declare_project_state( + "PROJ_POST_COMPLETE", + "proj_post_complete", + _("Completed Post-Processing"), + $pp_projects_forum_idx, + 'PP', + 'SILVER'); + + + +// SUBMIT (was GB) +declare_project_state( + "PROJ_SUBMIT_PG_POSTED", + "proj_submit_pgposted", + _("Posted"), + $posted_projects_forum_idx, + 'GB', + 'GOLD'); + +// CORRECT +declare_project_state( + "PROJ_CORRECT_AVAILABLE", + "proj_correct_available", + _("Verify Corrections"), + $posted_projects_forum_idx, + 'NONE', + 'GOLD'); +declare_project_state( + "PROJ_CORRECT_CHECKED_OUT", + "proj_correct_checked_out", + _("Verifying Corrections"), + $posted_projects_forum_idx, + 'NONE', + 'GOLD'); + +// for complete project +declare_project_state( + "PROJ_COMPLETE", + "project_complete", + _("Project Complete"), + -1, + 'COMPLETE', + ''); + +// for the 'deletion' of a project +declare_project_state( + "PROJ_DELETE", + "project_delete", + _("Delete Project"), + -1, + 'NONE', + ''); + +// ----------------------------------------------------------------------------- + +// Define constants for use in SQL queries: +// SQL_CONDITION_BRONZE +// SQL_CONDITION_SILVER +// SQL_CONDITION_GOLD + +foreach ( $project_states_for_star_metal_ as $star_metal => $project_states ) { + $sql_constant_name = "SQL_CONDITION_$star_metal"; + $sql_condition = '('; + foreach ( $project_states as $project_state ) { + if ($sql_condition != '(') { + $sql_condition .= ' OR '; + } + $sql_condition .= "state='$project_state'"; + } + $sql_condition .= ')'; + + define( $sql_constant_name, $sql_condition ); +} + +// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + +// In an SQL query, if you "ORDER BY state", it will use alphabetical order, +// which is not very useful. Instead, ORDER BY the result of this function, +// and it will use the canonical order-of-declaration for project states. +function sql_collater_for_project_state( $state_column ) { + global $PROJECT_STATES_IN_ORDER; + $s = "FIELD($state_column"; + foreach ( $PROJECT_STATES_IN_ORDER as $project_state ) { + $s .= ",'$project_state'"; + } + $s .= ")"; + return $s; +} + +// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + +// $which is a word denoting a possible status of a project +// (created, proofed, PPd, or posted). +// Return an object whose attributes hold various constants that +// are useful for: +// -- finding, +// -- counting, or +// -- plotting a graph of +// projects having that status. +// (Somewhat ad hoc, but useful.) +function get_project_status_descriptor( $which ) { + $obj = new stdClass; + + switch ( $which ) { + case 'created': + $obj->state_selector = " + ( state NOT LIKE 'project_new%' AND state != 'project_delete')"; + $obj->color = 'green'; + + $obj->Xed_title = _('Created'); + $obj->projects_Xed_title = _('Projects Created'); + $obj->graphs_title = _('Created Projects Graphs'); + $obj->per_day_title = _('Projects Created Each Day'); + $obj->cumulative_title = _('Cumulative Projects Created'); + break; + + case 'proofed': + $obj->state_selector = "( + state LIKE 'proj_submit%' + OR state LIKE 'proj_correct%' + OR state LIKE 'proj_post%')"; + $obj->color = 'blue'; + + $obj->Xed_title = _('Proofread'); + $obj->projects_Xed_title = _('Projects Proofread'); + $obj->graphs_title = _('Proofed Projects Graphs'); + $obj->per_day_title = _('Projects Proofed Each Day'); + $obj->cumulative_title = _('Cumulative Projects Proofed'); + break; + + case 'PPd': + $obj->state_selector = " + ( state LIKE 'proj_submit%' + OR state LIKE 'proj_correct%' + OR state LIKE 'proj_post_second%')"; + $obj->color = 'silver'; + $obj->Xed_title = _('Post-Processed'); + $obj->projects_Xed_title = _('Projects Post-Processed'); + $obj->graphs_title = _('PPd Projects Graphs'); + $obj->per_day_title = _('Projects Post-Processed Each Day'); + $obj->cumulative_title = _('Cumulative Projects PPd'); + break; + + case 'posted': + $obj->state_selector = " + ( state LIKE 'proj_submit%' OR state LIKE 'proj_correct%')"; + $obj->color = 'gold'; + $obj->Xed_title = _('Posted'); + $obj->projects_Xed_title = _('Projects Posted'); + $obj->graphs_title = _('Posted Projects Graphs'); + $obj->per_day_title = _('Projects Posted Each Day'); + $obj->cumulative_title = _('Cumulative Projects Posted'); + break; + + default: + die("bad value for 'which': '$which'"); + } + + return $obj; +} + +?> diff --git a/c/pinc/project_states_old.inc b/c/pinc/project_states_old.inc new file mode 100644 index 0000000..e8793fe --- /dev/null +++ b/c/pinc/project_states_old.inc @@ -0,0 +1,455 @@ + array(), + 'SILVER' => array(), + 'GOLD' => array(), +); + +function declare_project_state( + $constant_name, + $constant_value, + $label, + $forum, + $phase, + $star_metal ) +{ + global $PROJECT_STATES_IN_ORDER; + global $project_state_label_; + global $project_state_forum_; + global $project_state_phase_; + global $project_states_for_star_metal_; + + define( $constant_name, $constant_value ); + $PROJECT_STATES_IN_ORDER[] = $constant_value; + $project_state_label_[$constant_value] = $label; + $project_state_forum_[$constant_value] = $forum; + $project_state_phase_[$constant_value] = $phase; + if ($star_metal) $project_states_for_star_metal_[$star_metal][] = $constant_value; +} + +function project_states_text($state) +{ + global $project_state_label_; + return array_get( $project_state_label_, $state, '' ); +} + +function get_forum_id_for_project_state($state) +{ + global $project_state_forum_; + return array_get( $project_state_forum_, $state, -1 ); +} + +function get_phase_containing_project_state($state) +{ + global $project_state_phase_; + return array_get( $project_state_phase_, $state, 'NONE' ); +} + +// ----------------------------------------------- + +function declare_project_states_for_round( $round_id, $round_name ) +{ + global $projects_forum_idx; + global $waiting_projects_forum_idx; + + declare_project_state( + "PROJ_{$round_id}_BAD_PROJECT", + "$round_id.proj_bad", + "$round_name: " . _("Bad Project"), + $projects_forum_idx, + 'PAGE_EDITING', + '' + ); + declare_project_state( + "PROJ_{$round_id}_UNAVAILABLE", + "$round_id.proj_unavail", + "$round_name: " . _("Unavailable"), + ($round_id == 'P1' ? $waiting_projects_forum_idx : $projects_forum_idx ), + 'PAGE_EDITING', + '' + ); + declare_project_state( + "PROJ_{$round_id}_WAITING_FOR_RELEASE", + "$round_id.proj_waiting", + "$round_name: " . _("Waiting for Release"), + ($round_id == 'P1' ? $waiting_projects_forum_idx : $projects_forum_idx ), + 'PAGE_EDITING', + '' + ); + declare_project_state( + "PROJ_{$round_id}_AVAILABLE", + "$round_id.proj_avail", + "$round_name: " . _("Available"), + $projects_forum_idx, + 'PAGE_EDITING', + 'BRONZE' + ); + declare_project_state( + "PROJ_{$round_id}_COMPLETE", + "$round_id.proj_done", + "$round_name: " . _("Completed"), + $projects_forum_idx, + 'PAGE_EDITING', + '' + ); +} + +// ----------------------------------------------- + +// Note that the order in which these project states are declared +// is the order in which they will be displayed in various contexts +// (via $PROJECT_STATES_IN_ORDER). + + +// PR + + +// for the initial creation of a project +declare_project_state( + "PROJ_NEW", + "project_new", + _("New Project"), + $waiting_projects_forum_idx, + 'NEW', + '' +); + +if ($site_supports_metadata) +{ + declare_project_state( + "PROJ_NEW_WAITING_APPROVAL", + "project_new_waiting_app", + _("Awaiting Approval"), + $waiting_projects_forum_idx, + 'NONE', + '' + ); + declare_project_state( + "PROJ_NEW_UNAPPROVED", + "project_new_unapp", + _("Unapproved Project"), + $waiting_projects_forum_idx, + 'NONE', + '' + ); + declare_project_state( + "PROJ_NEW_APPROVED", + "project_new_app", + _("Approved Project"), + $waiting_projects_forum_idx, + 'NONE', + '' + ); + declare_project_state( + "PROJ_NEW_FILE_UPLOADED", + "project_new_uploaded", + _("Files Uploaded"), + $waiting_projects_forum_idx, + 'NONE', + '' + ); + declare_project_state( + "PROJ_NEW_METADATA_FIRST", + "project_md_first", + _("Metadata First Round"), + $waiting_projects_forum_idx, + 'NONE', + '' + ); + declare_project_state( + "PROJ_NEW_METADATA_BAD", + "project_md_bad", + _("Bad Metadata"), + $waiting_projects_forum_idx, + 'NONE', + '' + ); + declare_project_state( + "PROJ_NEW_METADATA_SECOND", + "project_md_second", + _("Metadata Second Round"), + $waiting_projects_forum_idx, + 'NONE', + '' + ); + declare_project_state( + "PROJ_NEW_PREPROCESSING", + "project_new_preprocess", + _("Preprocessing"), + $waiting_projects_forum_idx, + 'NONE', + '' + ); + declare_project_state( + "PROJ_NEW_PENDING_PM", + "project_new_pend_pm", + _("Pending Project Manager"), + $waiting_projects_forum_idx, + 'NONE', + '' + ); +} + + +// PROOF +declare_project_states_for_round( 'P1', _('Proofreading Round 1') ); +declare_project_states_for_round( 'P2', _('Proofreading Round 2') ); +declare_project_states_for_round( 'P3', _('Proofreading Round 3') ); + +// FORMAT +declare_project_states_for_round( 'F1', _('Formatting Round 1') ); +declare_project_states_for_round( 'F2', _('Formatting Round 2') ); + + +// POST +declare_project_state( + "PROJ_POST_FIRST_UNAVAILABLE", + "proj_post_first_unavailable", + _("Unavailable for Post-Processing"), + $pp_projects_forum_idx, + 'PP', + 'SILVER' +); +declare_project_state( + "PROJ_POST_FIRST_AVAILABLE", + "proj_post_first_available", + _("Available for Post-Processing"), + $pp_projects_forum_idx, + 'PP', + 'SILVER' +); + +declare_project_state( + "PROJ_POST_FIRST_CHECKED_OUT", + "proj_post_first_checked_out", + _("In Post-Processing"), + $pp_projects_forum_idx, + 'PP', + 'SILVER' +); + +declare_project_state( + "PROJ_POST_SECOND_AVAILABLE", + "proj_post_second_available", + _("Available for Verifying Post-Processing"), + $pp_projects_forum_idx, + 'PP', + 'SILVER' +); + +declare_project_state( + "PROJ_POST_SECOND_CHECKED_OUT", + "proj_post_second_checked_out", + _("Verifying Post-Processing"), + $pp_projects_forum_idx, + 'PP', + 'SILVER' +); +declare_project_state( + "PROJ_POST_COMPLETE", + "proj_post_complete", + _("Completed Post-Processing"), + $pp_projects_forum_idx, + 'PP', + 'SILVER' +); + + + +// SUBMIT (was GB) +declare_project_state( + "PROJ_SUBMIT_PG_POSTED", + "proj_submit_pgposted", + _("Posted to Project Gutenberg Canada"), + $posted_projects_forum_idx, + 'GB', + 'GOLD' +); + +// CORRECT +declare_project_state( + "PROJ_CORRECT_AVAILABLE", + "proj_correct_available", + _("Verify Corrections"), + $posted_projects_forum_idx, + 'NONE', + 'GOLD' +); +declare_project_state( + "PROJ_CORRECT_CHECKED_OUT", + "proj_correct_checked_out", + _("Verifying Corrections"), + $posted_projects_forum_idx, + 'NONE', + 'GOLD' +); + +// for complete project +declare_project_state( + "PROJ_COMPLETE", + "project_complete", + _("Project Complete"), + -1, + 'COMPLETE', + '' +); + +// for the 'deletion' of a project +declare_project_state( + "PROJ_DELETE", + "project_delete", + _("Delete Project"), + -1, + 'NONE', + '' +); + +// ----------------------------------------------------------------------------- + +// Define constants for use in SQL queries: +// SQL_CONDITION_BRONZE +// SQL_CONDITION_SILVER +// SQL_CONDITION_GOLD + +foreach ( $project_states_for_star_metal_ as $star_metal => $project_states ) +{ + $sql_constant_name = "SQL_CONDITION_$star_metal"; + $sql_condition = '('; + foreach ( $project_states as $project_state ) + { + if ($sql_condition != '(') + { + $sql_condition .= ' OR '; + } + $sql_condition .= "state='$project_state'"; + } + $sql_condition .= ')'; + + define( $sql_constant_name, $sql_condition ); +} + +// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + +function sql_collater_for_project_state( $state_column ) +// In an SQL query, if you "ORDER BY state", it will use alphabetical order, +// which is not very useful. Instead, ORDER BY the result of this function, +// and it will use the canonical order-of-declaration for project states. +{ + global $PROJECT_STATES_IN_ORDER; + $s = "FIELD($state_column"; + foreach ( $PROJECT_STATES_IN_ORDER as $project_state ) + { + $s .= ",'$project_state'"; + } + $s .= ")"; + return $s; +} + +// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + +function get_project_status_descriptor( $which ) +// $which is a word denoting a possible status of a project +// (created, proofed, PPd, or posted). +// Return an object whose attributes hold various constants that +// are useful for: +// -- finding, +// -- counting, or +// -- plotting a graph of +// projects having that status. +// (Somewhat ad hoc, but useful.) +{ + $obj = new stdClass; + + switch ( $which ) + { + case 'created': + $obj->state_selector = "( + state NOT LIKE 'project_new%' AND state != 'project_delete' + )"; + $obj->color = 'green'; + $obj->Xed_title = _('Created'); + $obj->projects_Xed_title = _('Projects Created'); + $obj->graphs_title = _('Created Projects Graphs'); + $obj->per_day_title = _('Projects Created Each Day'); + $obj->cumulative_title = _('Cumulative Projects Created'); + break; + + case 'proofed': + $obj->state_selector = "( + state LIKE 'proj_submit%' + OR state LIKE 'proj_correct%' + OR state LIKE 'proj_post%' + )"; + $obj->color = 'blue'; + $obj->Xed_title = _('Proofread'); + $obj->projects_Xed_title = _('Projects Proofread'); + $obj->graphs_title = _('Proofed Projects Graphs'); + $obj->per_day_title = _('Projects Proofed Each Day'); + $obj->cumulative_title = _('Cumulative Projects Proofed'); + break; + + case 'PPd': + $obj->state_selector = "( + state LIKE 'proj_submit%' + OR state LIKE 'proj_correct%' + OR state LIKE 'proj_post_second%' + )"; + $obj->color = 'silver'; + $obj->Xed_title = _('Post-Processed'); + $obj->projects_Xed_title = _('Projects Post-Processed'); + $obj->graphs_title = _('PPd Projects Graphs'); + $obj->per_day_title = _('Projects Post-Processed Each Day'); + $obj->cumulative_title = _('Cumulative Projects PPd'); + break; + + case 'posted': + $obj->state_selector = "( + state LIKE 'proj_submit%' + OR state LIKE 'proj_correct%' + )"; + $obj->color = 'gold'; + $obj->Xed_title = _('Posted to PG'); + $obj->projects_Xed_title = _('Projects Posted'); + $obj->graphs_title = _('Posted Projects Graphs'); + $obj->per_day_title = _('Projects Posted to PGC Each Day'); + $obj->cumulative_title = _('Cumulative Projects Posted to PGC'); + break; + + default: + die("bad value for 'which': '$which'"); + } + + return $obj; +} + +?> diff --git a/c/pinc/projectinfo.inc b/c/pinc/projectinfo.inc new file mode 100644 index 0000000..d8b1bae --- /dev/null +++ b/c/pinc/projectinfo.inc @@ -0,0 +1,17 @@ +SqlOneValue(" + SELECT COUNT(1) FROM $projectid + WHERE state='$page_state'"); +} + +function Project_getNumPages( $projectid ) { + global $dpdb; + return $dpdb->SqlOneValue(" + SELECT COUNT(*) FROM $projectid"); +} + +// vim: sw=4 ts=4 expandtab +?> diff --git a/c/pinc/quizzes.inc b/c/pinc/quizzes.inc new file mode 100644 index 0000000..284b202 --- /dev/null +++ b/c/pinc/quizzes.inc @@ -0,0 +1,31 @@ + 'formatting1', + _('Page two: Section headings, hyphens and em-dashes') => 'formatting2', + _('Page three: Chapter headings and thought breaks') => 'formatting3', + _('Page four: Poetry, blockquotes and lists') => 'formatting4', + _('Page five: Illustrations and footnotes') => 'formatting5'), + array( 'maximum_age' => 6 * 30 * 24 * 60 * 60) // 6 months +); + + +$PQ = new Quiz( "PQ", "Proofreading Quiz", + _("This quiz covers the corrections you should make in the proofreading rounds."), + array( _('Page One') => 'step1', + _('Page Two') => 'step2', + _('Page Three') => 'step3', + _('Page Four') => 'step4', + _('Page Five') => 'step5'), + array( 'maximum_age' => 6 * 30 * 24 * 60 * 60) // 6 months +); +*/ diff --git a/c/pinc/randrule.php b/c/pinc/randrule.php new file mode 100644 index 0000000..bcc9da8 --- /dev/null +++ b/c/pinc/randrule.php @@ -0,0 +1,27 @@ +SqlOneValue(" + SELECT count(*) AS numrules FROM rules"); + + $randid = rand(0, $num_rules); + + $rule = $dpdb->SqlOneRow(" + SELECT subject, rule, doc FROM rules + WHERE id = $randid"); + + return <<$rule[subject]

    + +

    $rule[rule]

    + +

    See the $rule[subject] section of the Proofreading Guidelines

    +EOT; +} +?> diff --git a/c/pinc/release_queue.inc b/c/pinc/release_queue.inc new file mode 100644 index 0000000..db8347d --- /dev/null +++ b/c/pinc/release_queue.inc @@ -0,0 +1,22 @@ + diff --git a/c/pinc/resolution.inc b/c/pinc/resolution.inc new file mode 100644 index 0000000..f2629da --- /dev/null +++ b/c/pinc/resolution.inc @@ -0,0 +1,5 @@ + diff --git a/c/pinc/root b/c/pinc/root new file mode 100644 index 0000000..70cd64b --- /dev/null +++ b/c/pinc/root @@ -0,0 +1,25 @@ +From root@powerweb.testfusionmedia.com Fri Sep 27 02:15:01 2013 +Return-Path: +Received: from powerweb.testfusionmedia.com (localhost [127.0.0.1]) + by powerweb.testfusionmedia.com (8.14.4/8.14.4) with ESMTP id r8R6F142007843 + for ; Fri, 27 Sep 2013 02:15:01 -0400 +Received: (from dkretz@localhost) + by powerweb.testfusionmedia.com (8.14.4/8.14.4/Submit) id r8R6F1Bf007842; + Fri, 27 Sep 2013 02:15:01 -0400 +Date: Fri, 27 Sep 2013 02:15:01 -0400 +Message-Id: <201309270615.r8R6F1Bf007842@powerweb.testfusionmedia.com> +X-Authentication-Warning: powerweb.testfusionmedia.com: dkretz set sender to root using -f +From: root@powerweb.testfusionmedia.com (Cron Daemon) +To: dkretz@powerweb.testfusionmedia.com +Subject: Cron /sharehome/htdocs/c/tools/project_manager/auto.sh > /sharehome/cronlogs/automodify.log +Content-Type: text/plain; charset=UTF-8 +Auto-Submitted: auto-generated +X-Cron-Env: +X-Cron-Env: +X-Cron-Env: +X-Cron-Env: +X-Cron-Env: +Status: O + +PHP Notice: Undefined index: REQUEST_URI in /sharehome/htdocs/c/pinc/dp_main.inc on line 38 + diff --git a/c/pinc/rounds.php b/c/pinc/rounds.php new file mode 100644 index 0000000..891d8fa --- /dev/null +++ b/c/pinc/rounds.php @@ -0,0 +1,249 @@ + "PREP", 1 => "P1", 2 => "P2", 3 => "P3", 4 => "F1", 5 => "F2", + 6 => "PP", 7 => "PPV", 8 => "POSTED"); + } + + function PhaseForRoundId($roundid) { + switch($roundid) { + case "OCR": + return "PREP"; + case "P1": + case "P2": + case "P3": + case "F1": + case "F2": + return $roundid; + default: + return null; + } + } + + function PhaseForIndex($index) { + $p = PhasesInOrder(); + return $p[$index]; + } + + function IndexForPhase($phase) { + $p = PhasesInOrder(); + return array_search($phase, $p); + } + + function RoundIdsInOrder() { + return array("P1", "P2", "P3", "F1", "F2"); + // global $dpdb; + // static $_ids; + // if(!isset($_ids)) { + // $sql = " + // SELECT roundid FROM rounds + // ORDER BY round_index"; + // $_ids = $dpdb->SqlValues($sql); + // } + // return $_ids; + } + + function RoundCount() { + return 5; + } + + function RoundIndexForId($roundid) { + switch(strtoupper($roundid)) { + case "OCR": + return 0; + case "P1": + return 1; + case "P2": + return 2; + case "P3": + return 3; + case "F1": + return 4; + case "F2": + return 5; + default: + return null; + } + } + + function RoundIdBefore($roundid) { + switch($roundid) { + case "P1": + return "PREP"; + case "P2": + return "P1"; + case "P3": + return "P2"; + case "F1": + return "P3"; + case "F2": + return "F1"; + default: + return null; + } + // $index = RoundIndexForId($roundid); + // if($index == 0) + // return null; + // return RoundIdForIndex($index - 1); + } + + function RoundIdAfter($roundid) { + switch($roundid) { + case "OCR": + return "P1"; + case "P1": + return "P2"; + case "P2": + return "P3"; + case "P3": + return "F1"; + case "F1": + return "F2"; + case "F2": + return "proj_post_first_available"; + default: + return null; + } + // $index = RoundIndexForId($roundid); + // if($index >= 6) + // return null; + // return RoundIdForIndex(RoundIndexForId($roundid) + 1); + } + + function RoundIdForIndex($index) { + switch($index) { + case 0: + return "OCR"; + case 1: + return "P1"; + case 2: + return "P2"; + case 3: + return "P3"; + case 4: + return "F1"; + case 5: + return "F2"; + default: + return null; + + } + } + + function UserFieldForRoundIndex($index) { + if($index < 1 || $index > 5) { + return ""; + } + return sprintf("%s%d%s", "round", $index, "_user"); + } + + function TimeFieldForRoundIndex($index) { + return sprintf("%s%d%s", "round", $index, "_time"); + } + + function TextFieldForRoundIndex($index) { + if($index == 0) { + return "master_text"; + } + return sprintf("%s%d%s", "round", $index, "_text"); + } + + + function TextFieldForPhase($phase) { + switch($phase) { + case "PREP": + return "master_text"; + case "P1": + return "round1_text"; + case "P2": + return "round2_text"; + case "P3": + return "round3_text"; + case "F1": + return "round4_text"; + case "F2": + return "round5_text"; + default: + return "round5_text"; + } + } + + function TextFieldForRoundId($roundid) { + switch($roundid) { + case "OCR": + return "master_text"; + case "P1": + return "round1_text"; + case "P2": + return "round2_text"; + case "P3": + return "round3_text"; + case "F1": + return "round4_text"; + case "F2": + return "round5_text"; + default: + return "round5_text"; + } + } + + function PreviousUserFieldForRoundid($roundid) { + switch($roundid) { + case "P2": + return "round1_user"; + case "P3": + return "round2_user"; + case "F1": + return "round3_user"; + case "F2": + return "round4_user"; + default: + return null; + } + } + + function UserFieldForRoundId($roundid) { + switch($roundid) { + case "P1": + return "round1_user"; + case "P2": + return "round2_user"; + case "P3": + return "round3_user"; + case "F1": + return "round4_user"; + case "F2": + return "round5_user"; + default: + return null; + } + } + + function TimeFieldForRoundId($roundid) { + return TimeFieldForRoundIndex(RoundIndexForId($roundid)); + } + + + function FirstRoundId() { + return RoundIdForIndex(0); + } + + function PreviousRoundIdForRoundId($roundid) { + $idx = RoundIndexForId($roundid) - 1; + if($idx < 1) { + return null; + } + return RoundIdForIndex($idx); + } + + function NextRoundIdForRoundId($roundid) { + $idx = RoundIndexForId($roundid) + 1; + if($idx > 5 ){ + return null; + } + return RoundIdForIndex($idx); + } + + function RoundUrl($roundid) { + global $proof_url; + return "{$proof_url}/round.php?roundid={$roundid}"; + } diff --git a/c/pinc/select_list.inc b/c/pinc/select_list.inc new file mode 100644 index 0000000..241a98c --- /dev/null +++ b/c/pinc/select_list.inc @@ -0,0 +1,17 @@ +SqlValues(" + SELECT distinct $field FROM projects + WHERE $states + ORDER BY $field"); + + foreach($values as $val) { + $to_echo .= "\n"; +} + +/*************************************************************************************** +* +* function sr_echo_withdrawal_form: create button and call page for database access +* inputs: projectid +* output: none +* +* Remarks: +* This calls a transient page executing the database function for revoking a commitment +* and provides the current URI for return to current page. +* +****************************************************************************************/ + +function sr_echo_withdrawal_form($projectid) { + global $code_url; + + $next_url = $_SERVER['REQUEST_URI']; + $button_text = _("Withdraw SR commitment"); + + echo " +
    + + + + +
    \n"; + +} + + +?> diff --git a/c/pinc/special_colors.inc b/c/pinc/special_colors.inc new file mode 100644 index 0000000..e2a3848 --- /dev/null +++ b/c/pinc/special_colors.inc @@ -0,0 +1,123 @@ +
    "; + + $currspecs_result = mysql_query(" + SELECT distinct special_code as spec FROM projects + WHERE $projects_where_clause + "); + + $curr_specs_array = array(); + + while ($cs_row = mysql_fetch_assoc($currspecs_result)) { + + $curr_specs_array[] = $cs_row['spec']; + } + + $specs_result = mysql_query(" + SELECT spec_code, display_name, color FROM special_days + WHERE 1 = 1 + ORDER BY open_month desc, open_day desc + "); + + $running_length = 0; + $span_prefix = ""; + $span_suffix = " "; + + while ($sr_row = mysql_fetch_assoc($specs_result)) { + if (in_array($sr_row['spec_code'], $curr_specs_array)) { + echo $span_prefix.$sr_row['color'].$span_midfix.$sr_row['display_name'].$span_suffix ; + $running_length = $running_length + strlen($sr_row['display_name']) + 1; + if ($running_length > 60) { + echo "
    "; + $running_length = 0; + } + } + } + + if ($running_length > 0) { + echo "
    "; + } + + echo $span_prefix."CCFFFF".$span_midfix._("Authors with recent birthdays").$span_suffix; + echo $span_prefix."33CCFF".$span_midfix._("Authors with birthdays today").$span_suffix; + echo "
    "; + echo $span_prefix."FFFF66".$span_midfix._("Other Special").$span_suffix; + echo "
    "; + echo "
    "; + +} + +?> diff --git a/c/pinc/stages.inc b/c/pinc/stages.inc new file mode 100644 index 0000000..233892b --- /dev/null +++ b/c/pinc/stages.inc @@ -0,0 +1,360 @@ + array('search_and_replace', + 'greek_transliterator'), + 'tool_buttons' => array('remove_markup', + 'upper_case', + 'title_case', + 'lower_case'), + 'tool_links' => array('greek', + 'note', + 'curlybraces', + 'brackets', + 'blank_page'), +); +$pi_tools_for_F = array( 'popup_links' => 'ALL', + 'tool_buttons' => 'ALL', + 'tool_links' => 'ALL', +); + +new Round( + 'P1', + _('Proofreading Round 1'), + array(), + 'IMMEDIATE', + _("The page-texts are the output from OCR software and need to have the text carefully compared to the image."), + $site_url."/wiki/index.php/Proofreading_Guidelines", + array( + 0 => '#FFE4B5', // mocassin + 1 => '#FFF8DC', // cornsilk + ), + $pi_tools_for_P, + array(), + array( + 0 => _('Novice'), + 25 => _('Proofreading Pupil'), + 100 => _('Proofreading Apprentice'), + 500 => _('Proofreading Scholar'), + 1000 => _('Proofreading Prodigy'), + 2500 => _('Prefect of Proofreaders'), + 5000 => _('Proofreading Graduate'), + 10000 => _('Proofreading Alumnus'), + 20000 => _('Fellow of Proofreading'), + 30000 => _('Doctor of Proofreading'), + 40000 => _('Proofreading Don'), + 50000 => _('Dean of Proofreading'), + 60000 => _('Proofreading Proctor'), + 70000 => _('Principal Proofreader'), + 80000 => _('Master Proofreader'), + 90000 => _('Prefect of Proofreaders'), + 99000 => _('Supervising Proofreader'), + 100000 => _('Proofreading Professor'), + 110000 => _('Peer of Proofreading'), + 120000 => _('Doyen of Proofreading'), + 130000 => _('Proofreading Chancellor'), + 140000 => _('Proofreading Primate'), + 150000 => _('Paramount Proofreader'), + ) +); + +// ----------------------------------------------------------------------------- + +new Round( + 'P2', + _('Proofreading Round 2'), + array( 'P1' => 300, 'days since reg' => 21, 'quiz/P' => 1 ), + 'REQ-AUTO', + _("The page-texts have been proofread once, and now need to carefully compared to the image again."), + $site_url."/wiki/index.php/Proofreading_Guidelines", + array( + 0 => '#FFE4B5', // mocassin + 1 => '#FFF8DC', // cornsilk + ), + $pi_tools_for_P, + array( 'P1' ), + array( + 0 => _('Precise Proofreader'), + 25 => _('Picky Proofreader'), + 100 => _('Painstaking Proofreader'), + 500 => _('Punctilious Proofreader'), + 1000 => _('Persnickety Proofreader'), + 2500 => _('Particular Proofreader'), + 5000 => _('Proficient Proofreader'), + 10000 => _('Proper Proofreader'), + 20000 => _('Prudent Proofreader'), + 30000 => _('Proofreading Personage'), + 40000 => _('Proofreading Poppet'), + 50000 => _('Plighted Proofreader'), + 60000 => _('Proofreading Proctor'), + 70000 => _('Principal Proofreader'), + 80000 => _('Prime Proofreader'), + 90000 => _('Primal Proofreader'), + 99000 => _('Proofreading Personality'), + 100000 => _('Proofreading Professional'), + 110000 => _('Peerless Proofreader'), + 120000 => _('Plighted Proofreader'), + 130000 => _('Paraproofreader'), + 140000 => _('Proofreading Panjandrum'), + 150000 => _('Perfectionist Proofreader'), + ) +); + +// ----------------------------------------------------------------------------- + +new Round( + 'P3', + _('Proofreading Round 3'), + array( 'P1+P2' => 400, 'F1' => 50, 'days since reg' => 42, 'quiz/P' => 1 ), + 'REQ-HUMAN', + _("The page-texts have already been proofread, but now need to be examined closely for small errors that may have been missed."), + $site_url."/wiki/index.php/Proofreading_Guidelines", + array( + 0 => '#DDA0DD', // plum + 1 => '#D8BFD8', // thistle + ), + $pi_tools_for_P, + array( 'P1', 'P2' ), + array( + 0 => _('Specialist Proofreader'), + 25 => _('Precious Proofreader'), + 100 => _('Prized Proofreader'), + 500 => _('Premiere Proofreader'), + 1000 => _('Proofreading Perfectionist'), + 2500 => _('Pillar of Proofreading'), + 5000 => _('Proofreading Purist'), + 10000 => _('Proofreader of Precision'), + 20000 => _('Archetypal Proofreader'), + 30000 => _('Proofreading Nonpareil'), + 40000 => _('Paradigmatic Proofreader'), + 50000 => _('Preeminent Proofreader'), + 60000 => _('Prime Proofreader'), + 70000 => _('Proofreader of Plenariness'), + 80000 => _('Perpetual Proofreader'), + 90000 => _('Prefect of Proofreaders'), + 99000 => _('Impeccable Proofreader'), + 100000 => _('Proofreader of Persistence'), + 110000 => _('Patent Proofreader'), + 120000 => _('Proofreading Philosopher'), + 130000 => _('Patron of Proofreaders'), + 140000 => _('Proofreading Partner'), + 150000 => _('Pioneer of Proofreaders'), + ) +); + +// ----------------------------------------------------------------------------- + +new Round( + 'F1', + _('Formatting Round 1'), + array( 'P1' => 300, 'days since reg' => 21, 'quiz/F' => 1 ), + 'REQ-AUTO', + _("The page-texts have been proofread, and now need to be formatted with markup which may be specific to the project."), + $site_url."/wiki/index.php/Formatting_Guidelines", + array( + 0 => '#FFE4B5', // mocassin + 1 => '#FFF8DC', // cornsilk + ), + $pi_tools_for_F, + array(), + array( + 0 => _('Formatting Neophyte'), + 25 => _('Formatting Intern'), + 100 => _('Journeyman Formatter'), + 500 => _('Crafter of Texts'), + 1000 => _('Detailer of Books'), + 2500 => _('Fastidious Formatter'), + 5000 => _('Foremost Formatter'), + 10000 => _('Fine Formatter'), + 20000 => _('Flamboyant Formatter'), + 30000 => _('Fabulous Formatter'), + 40000 => _('Upgrader of Texts'), + 50000 => _('Famous Formatter'), + 60000 => _('Indefatigible Formatter'), + 70000 => _('Finisher of Texts'), + 80000 => _('Formatter of Choice'), + 90000 => _('Capital Formatter'), + 99000 => _('Formatter with Flair'), + 100000 => _('Formatter of Finesse'), + 110000 => _('Formatter with Forte'), + 120000 => _('First-Class Formatter'), + 130000 => _('Formatter of Favour'), + 140000 => _('Formatter of Refinement'), + 150000 => _('Flawless Formatter'), + ) +); + +// ----------------------------------------------------------------------------- + +new Round( + 'F2', + _('Formatting Round 2'), + array( 'F1' => 400, 'days since reg' => 91 ), // 'F1' => 1000, 3 months after rollout + 'REQ-HUMAN', // "peer approval" + _("The page-texts in this round need to be carefully checked to refine the formatting markup."), + $site_url."/wiki/index.php/Formatting_Guidelines", + array( + 0 => '#DDA0DD', // plum + 1 => '#D8BFD8', // thistle + ), + $pi_tools_for_F, + array( 'F1' ), + array( + 0 => _('Refurbisher of Texts'), + 25 => _('Sprucer of Texts'), + 100 => _('Formatter Savant'), + 500 => _('Formatting Wunderkind'), + 1000 => _('Elite Formatter'), + 2500 => _('Polisher of Texts'), + 5000 => _('Formatting Artiste'), + 10000 => _('Cultivator of Texts'), + 20000 => _('Formatter of Enrichment'), + 30000 => _('Designing Formatter'), + 40000 => _('Formatting Artisan'), + 50000 => _('Formatting Afficiando'), + 60000 => _('Guru of Formatters'), + 70000 => _('Formatting Familiar'), + 80000 => _('Formatting Virtuoso'), + 90000 => _('Formatter of Excellence'), + 99000 => _('Exquisite Formatter'), + 100000 => _('Elite Formatter'), + 110000 => _('Formatting Genius'), + 120000 => _('Formatter of Fine Feats'), + 130000 => _('Harmoniser of Texts'), + 140000 => _('Formatting Architect'), + 150000 => _('Preserver of Texts'), + ) +); + +// --------------------------- + +// After creating all rounds: + +define('MAX_NUM_PAGE_EDITING_ROUNDS', 5); +assert( $n_rounds == MAX_NUM_PAGE_EDITING_ROUNDS ); + +declare_mentoring_pair( 'P1', 'P2' ); + +// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + +$someone_maintains_the_PP_faq = + sprintf( _("%s (%s) maintains our Post-Processing FAQ."), + 'Julie Barkley DP-INT', + url_for_pm('simple simon'), + 'simple simon', + "$code_url/faq/post_proof.php" ); + +new Pool( + 'PP', + _('Post-Processing'), + array( 'F1' => 400 ), + 'REQ-AUTO', + _('After going through various rounds of proofreading and formatting, the books need to be massaged into a final e-text.'), + 'post_proof.php', + array( + '#cccccc', + '#ffffff' + ), + + PROJ_POST_FIRST_CHECKED_OUT, + PROJ_POST_FIRST_AVAILABLE, + + _("Manager"), + 'username', + + array( + "

    ", + _("Each book listed below has gone through two rounds of proofreading and two rounds of formatting, and now needs to be massaged into a final e-text."), + _("Once you have checked out and downloaded a book it will remain checked out to you until you check it back in."), + _("When you have finished your work on the book, select Upload for Verification from the drop-down list for that project."), + _("If you have several files to submit for a single project (say a text and HTML version), zip them up together first."), + "

    ", + + "

    ", + "" . _("First Time Here?") . "", + _("Please read the FAQ as it covers all the steps needed to post-process an e-text."), + _("Select an easy work to get started on (usually fiction with a low page count is a good starter book; projects whose manager is BEGIN make excellent first projects for a new post-processor)."), + sprintf( _("Check out the Post-Processing Forum to post all your questions."), $post_processing_forum_url ), + _("If nothing interests you right now, check back later and there will be more!"), + "

    ", + ) +); + +// ----------------------------------------------------------------------------- + +new Stage( + 'SR', + _('Smooth Reading'), + array(), + 'IMMEDIATE', + _('Before a PPer has submitted a final e-text, they can optionally make it available for Smooth Reading. Anyone can volunteer to Smooth Read a text, which is basically just reading through it and marking possible errors before returning it to the Post-Processor.'), + NULL, + array( + '#CCFFCC', + '#CCFF99', + ), + "tools/post_proofers/smooth_reading.php" +); + +// ----------------------------------------------------------------------------- + +new Pool( + 'PPV', + _('Post-Processing Verification'), + array(), + 'NOREQ', // "Peer approval. Also gives F2 access." + _('Once a PPer has submitted a final e-text, it needs to be checked by a PPVer before it is posted to PGC.'), + 'ppv.php', + array( + '#99FFFF', // "harshflourolightblue" + '#EAF7F7', // "paledarkskyblue" + ), + + PROJ_POST_SECOND_CHECKED_OUT, + PROJ_POST_SECOND_AVAILABLE, + + _("Post-Processor"), + 'postproofer', + + array( + "

    ", + _("In this pool, experienced volunteers verify texts that have already been Post-Processed, and mentor new Post-Processors."), + "", + sprintf( _("Before working in this pool, make sure you read the new Post-Processing Verification Guidelines and use the PPV Report Card for each project you PPV."), + "http://www.pgdpcanada.net/wiki/index.php/Post-Processing_Verification_Guidelines", + "$code_url/faq/ppv_report.txt" ), + "", + "

    ", + + "

    ", + sprintf( _("As always, the Post-Processing Forum is available for any of your questions."), + $post_processing_forum_url ), + "

    ", + ) +); + +// ----------------------------------------------------------------------------- + + +// vim: sw=4 ts=4 expandtab diff --git a/c/pinc/stats.php b/c/pinc/stats.php new file mode 100644 index 0000000..9c48352 --- /dev/null +++ b/c/pinc/stats.php @@ -0,0 +1,95 @@ +SqlOneValue(" + SELECT goal FROM phase_goals + WHERE phase = '$phase' + AND goal_date = '$phdate'"); +} + +function PhaseGoalToday($phase) { + global $dpdb; + return $dpdb->SqlOneValue(" + SELECT goal FROM phase_goals + WHERE phase = '$phase' + AND goal_date = CURRENT_DATE()"); +} +function PhaseGoalYesterday($phase) { + global $dpdb; + return $dpdb->SqlOneValue(" + SELECT goal FROM phase_goals + WHERE phase = '$phase' + AND goal_date = DATE_ADD(CURRENT_DATE(), INTERVAL -1 DAY)"); +} + +function PhaseGoalMonth($phase) { + global $dpdb; + return $dpdb->SqlOneValue(" + SELECT SUM(goal) FROM phase_goals + WHERE phase = '$phase' + AND goal_date >= DATE(DATE_FORMAT(NOW() ,'%Y-%m-01')) + AND goal_date < DATE_ADD(DATE(DATE_FORMAT( + NOW(), + '%Y-%m-01')), INTERVAL 1 MONTH)"); +} + +function PhaseCountToday($phase) { + global $dpdb; + return $dpdb->SqlOneValue(" + SELECT COUNT(1) FROM page_events_save + WHERE round_id = '$phase' + AND timestamp >= UNIX_TIMESTAMP(CURRENT_DATE())"); +} + +function PhaseCountYesterday($phase) { + global $dpdb; + return $dpdb->SqlOneValue(" + SELECT COUNT(1) FROM page_events_save + WHERE round_id = '$phase' + AND timestamp >= UNIX_TIMESTAMP(DATE_SUB(CURRENT_DATE(), INTERVAL 1 day)) + AND timestamp < UNIX_TIMESTAMP(CURRENT_DATE())"); +} + +function PhaseCountMonth($phase) { + global $dpdb; + return $dpdb->SqlOneValue(" + SELECT SUM(pagecount) + FROM + ( SELECT SUM(urp.page_count) pagecount + FROM user_round_pages urp + WHERE round_id = '$phase' + AND count_time >= UNIX_TIMESTAMP(DATE(DATE_FORMAT(NOW() ,'%Y-%m-01'))) + UNION ALL + SELECT COUNT(1) pagecount + FROM page_events_save + WHERE round_id = '$phase' + AND TIMESTAMP > UNIX_TIMESTAMP(CURRENT_DATE()) + ) a"); +} + +function ExtendPhaseGoals() { + global $dpdb; + + $ago = $dpdb->SqlOneValue(" + SELECT DATEDIFF(MAX(goal_date), CURRENT_DATE()) FROM phase_goals + "); + dump($ago); + + for($i = $ago; $i <= 31; $i++) { + $dpdb->SqlExecute(" + REPLACE INTO phase_goals + (goal_date, PHASE, goal) + SELECT DATE_ADD(CURRENT_DATE(), INTERVAL $i DAY), PHASE, goal + FROM phase_goals + WHERE goal_date = ( + SELECT MAX(goal_date) FROM phase_goals + )"); + } +} + +// vim: sw=4 ts=4 expandtab + + diff --git a/c/pinc/tabs.inc b/c/pinc/tabs.inc new file mode 100644 index 0000000..dbb380d --- /dev/null +++ b/c/pinc/tabs.inc @@ -0,0 +1,125 @@ + + + + + diff --git a/c/pinc/templates/base_graphics/donate.psd b/c/pinc/templates/base_graphics/donate.psd new file mode 100644 index 0000000..f551fb1 Binary files /dev/null and b/c/pinc/templates/base_graphics/donate.psd differ diff --git a/c/pinc/templates/base_graphics/l_curve.psd b/c/pinc/templates/base_graphics/l_curve.psd new file mode 100644 index 0000000..7303979 Binary files /dev/null and b/c/pinc/templates/base_graphics/l_curve.psd differ diff --git a/c/pinc/templates/base_graphics/logo.psd b/c/pinc/templates/base_graphics/logo.psd new file mode 100644 index 0000000..77150c6 Binary files /dev/null and b/c/pinc/templates/base_graphics/logo.psd differ diff --git a/c/pinc/templates/base_graphics/r_curve.psd b/c/pinc/templates/base_graphics/r_curve.psd new file mode 100644 index 0000000..a4ed5af Binary files /dev/null and b/c/pinc/templates/base_graphics/r_curve.psd differ diff --git a/c/pinc/templates/base_graphics/tab.psd b/c/pinc/templates/base_graphics/tab.psd new file mode 100644 index 0000000..9e38e0d Binary files /dev/null and b/c/pinc/templates/base_graphics/tab.psd differ diff --git a/c/pinc/templates/base_graphics/tab_on.psd b/c/pinc/templates/base_graphics/tab_on.psd new file mode 100644 index 0000000..b1c179b Binary files /dev/null and b/c/pinc/templates/base_graphics/tab_on.psd differ diff --git a/c/pinc/templates/base_graphics/tabs_howto.txt b/c/pinc/templates/base_graphics/tabs_howto.txt new file mode 100644 index 0000000..c3ddc25 --- /dev/null +++ b/c/pinc/templates/base_graphics/tabs_howto.txt @@ -0,0 +1,34 @@ +How to create a tab-set resembling that of theme "Project Gutenberg" using Photoshop +------------------------------------------------------------------------------------ + +Edit theme.tpl +* It should contain something like + $royal_blues['tabs'] = array( + 'background' => '#ffffff', + 'background-position' => 'top', + 'padding-left' => '9px', + ); +* '9px' is the width of tabs_left.png created below and shouldn't need to be changed +* Obviously, '$royal_blues' should be something else +* '#ffffff' should likely be something else + +Create background image +* Create a new image, 10 pixels wide and 90 pixels high (approximately) +* Play around with the gradient tool, creating a vertical gradient +* Save as tabs_bg.png + +Note: In all of the four files referenced below, you may want to tweak the color of the border. + +Create parts of active tabs +For each of tabs_left_on.png and tabs_right_on.png, do this: +* Open the file from the gutenberg theme +* Select the greenish color using the sampler and "Select->Color Range..." +* Fill the selected area with the new color +* Save using the same filename but in the new directory using "Help->Export transparent image" + +Create parts of inactive tabs +For each of tabs_left.png and tabs_right.png, do this: +* Open the file from the gutenberg theme +* Select the greenish color using the sampler and "Select->Color Range..." +* Fill the selected area with approximately 70% of the new color +* Save using the same filename but in the new directory using "Help->Export transparent image" \ No newline at end of file diff --git a/c/pinc/templates/base_graphics/theme.tpl b/c/pinc/templates/base_graphics/theme.tpl new file mode 100644 index 0000000..273cf00 --- /dev/null +++ b/c/pinc/templates/base_graphics/theme.tpl @@ -0,0 +1,59 @@ + '#ffffff', + 'background-position' => 'bottom', + 'padding-left' => '5px', + // + // If you provide a key 'use_default_graphics' with a TRUE value, + // a default tab-layout will be used. You can still specify + // a background-color using a 'background'-key. If you don't, + // the $theme['color_navbar_bg']-value will be used. + // 'use_default_graphics' => true, +); +?> \ No newline at end of file diff --git a/c/pinc/templates/classic_grey/graphics/donate.gif b/c/pinc/templates/classic_grey/graphics/donate.gif new file mode 100644 index 0000000..2ca03ea Binary files /dev/null and b/c/pinc/templates/classic_grey/graphics/donate.gif differ diff --git a/c/pinc/templates/classic_grey/graphics/l_curve.gif b/c/pinc/templates/classic_grey/graphics/l_curve.gif new file mode 100644 index 0000000..9ed80a4 Binary files /dev/null and b/c/pinc/templates/classic_grey/graphics/l_curve.gif differ diff --git a/c/pinc/templates/classic_grey/graphics/logo.gif b/c/pinc/templates/classic_grey/graphics/logo.gif new file mode 100644 index 0000000..e39e0f6 Binary files /dev/null and b/c/pinc/templates/classic_grey/graphics/logo.gif differ diff --git a/c/pinc/templates/classic_grey/graphics/oldlogo.gif b/c/pinc/templates/classic_grey/graphics/oldlogo.gif new file mode 100644 index 0000000..d162b4d Binary files /dev/null and b/c/pinc/templates/classic_grey/graphics/oldlogo.gif differ diff --git a/c/pinc/templates/classic_grey/graphics/r_curve.gif b/c/pinc/templates/classic_grey/graphics/r_curve.gif new file mode 100644 index 0000000..b3f9d71 Binary files /dev/null and b/c/pinc/templates/classic_grey/graphics/r_curve.gif differ diff --git a/c/pinc/templates/classic_grey/graphics/tabs_bg.png b/c/pinc/templates/classic_grey/graphics/tabs_bg.png new file mode 100644 index 0000000..9616769 Binary files /dev/null and b/c/pinc/templates/classic_grey/graphics/tabs_bg.png differ diff --git a/c/pinc/templates/classic_grey/graphics/tabs_left.png b/c/pinc/templates/classic_grey/graphics/tabs_left.png new file mode 100644 index 0000000..c1b04f5 Binary files /dev/null and b/c/pinc/templates/classic_grey/graphics/tabs_left.png differ diff --git a/c/pinc/templates/classic_grey/graphics/tabs_left_on.png b/c/pinc/templates/classic_grey/graphics/tabs_left_on.png new file mode 100644 index 0000000..8e6aaa2 Binary files /dev/null and b/c/pinc/templates/classic_grey/graphics/tabs_left_on.png differ diff --git a/c/pinc/templates/classic_grey/graphics/tabs_right.png b/c/pinc/templates/classic_grey/graphics/tabs_right.png new file mode 100644 index 0000000..d1c04f8 Binary files /dev/null and b/c/pinc/templates/classic_grey/graphics/tabs_right.png differ diff --git a/c/pinc/templates/classic_grey/graphics/tabs_right_on.png b/c/pinc/templates/classic_grey/graphics/tabs_right_on.png new file mode 100644 index 0000000..9c1dd23 Binary files /dev/null and b/c/pinc/templates/classic_grey/graphics/tabs_right_on.png differ diff --git a/c/pinc/templates/classic_grey/main.css b/c/pinc/templates/classic_grey/main.css new file mode 100644 index 0000000..74eb086 --- /dev/null +++ b/c/pinc/templates/classic_grey/main.css @@ -0,0 +1,4 @@ + +tt { + color: #c00; +} diff --git a/c/pinc/templates/classic_grey/theme.tpl b/c/pinc/templates/classic_grey/theme.tpl new file mode 100644 index 0000000..f59bc25 --- /dev/null +++ b/c/pinc/templates/classic_grey/theme.tpl @@ -0,0 +1,48 @@ + '#cccccc', + 'background-position' => 'top', + 'padding-left' => '9px', +); +?> \ No newline at end of file diff --git a/c/pinc/templates/comment_files/BG1a.txt b/c/pinc/templates/comment_files/BG1a.txt new file mode 100644 index 0000000..1dd3817 --- /dev/null +++ b/c/pinc/templates/comment_files/BG1a.txt @@ -0,0 +1,6 @@ +

    Welcome New Volunteers!!

    +

    This is a BEGINNERS ONLY/FEEDBACK project. We have set this book aside for our newest proofreaders. You are doing the first of two proofing passes over these pages, making sure the words and punctuation in the text box match those in the scanned picture (or image) of the printed page. When the book has completed the first round of proofing, more experienced proofers will do a second round. They will send you some friendly suggestions if you are making any obvious beginner mistakes. Please only do a few pages (5-15) of this book, then move on to something else. It may be a week before feedback is sent to your DP inbox; so do work on another project that interests you while you're waiting!

    + +

    Please note that the proofers who review your work only see one page at a time; they do not have an overview of all the pages you proof in this book. You might get similar comments from several proofers. Please excuse any repetition!

    + +

    Following these two proofing rounds, these pages will move on to two rounds of formatting, where other volunteers will fine-tune the look of the page. They'll make sure that font variations (such as italics, bold, and small caps), spacing, indentation, footnotes, and the like are correctly marked. In the final stages, a post-processor will transform the proofed and formatted text into a readable e-book. If you wish to be notified when this text is posted to PG, click on the link above to request this.

    \ No newline at end of file diff --git a/c/pinc/templates/comment_files/BG1b.txt b/c/pinc/templates/comment_files/BG1b.txt new file mode 100644 index 0000000..7b78ecc --- /dev/null +++ b/c/pinc/templates/comment_files/BG1b.txt @@ -0,0 +1,124 @@ +

    BASIC INSTRUCTIONS:

    +

    Here are a few basic instructions. Please consult the +Proofreading +Guidelines to go beyond these basics.

    + +

    Make the text look like the page image except as +per below! That means leaving in the breaks at the +ends of the lines, leaving spelling "mistakes", etc. Mostly +your job is to fix mistakes left by the Optical Character +Recognition (OCR) software. Compare the text carefully +to the scanned image of the page, line by line (or word +by word, or letter by letter). Please pay extra-close attention +to punctuation, numbers, and words in ALL CAPS. Run a +spell-check on your page, and verify that any queried +words do, in fact, match the words in the scan. Please do +NOT correct the word in the text if it is a true match to +the word in the scan. Refer to the Proofreading +Guidelines for more information on handling printers' +errors and misspellings.

    + +

    ---1. If a line ends in a hyphenated word, move the first +part of the following line up to rejoin the word, then insert +a line break at the end of the rejoined word. Remove the +hyphen unless it is a compound word normally hyphenated.

    + +

    Scan Example: +
    "I say, Graham, do you know what's hap-
    +pened today? There'll be an awful row about it."

    +

    Corrected Example: +
    "I say, Graham, do you know what's happened
    +today? There'll be an awful row about it."

    + +

    ---2. Leave in (or add) the blank line between paragraphs. +Do not add paragraph indentation, but if the indentation is +present in the text box, it is not necessary to remove it.

    +

    Scan Example: +
    THE ship moved slowly out of the harbour as Tom Woodward slumped +
    in his seat and breathed a sigh of relief. +
        He turned to the package he had dropped next to him on the deck +
    and examined its label.

    +

    Corrected Example: +
    THE ship moved slowly out of the harbour as Tom Woodward slumped +
    in his seat and breathed a sigh of relief.

    +

        He turned to the package he had dropped next to him on the deck +
    and examined its label.

    + +

    ---3. Remove extra space around punctuation. Make it look like common usage today.

    +

    Scan Example: +
    The girl looked at him with tears in her eyes ; she began to cry. +

    Corrected Example: +
    The girl looked at him with tears in her eyes; she began to cry.

    + +

    ---4. Remove spaces in words with contractions like "don't" and "isn't"

    +

    Scan Example: +"Do n't!" he cried. "You 'll ruin the whole thing!" +

    Corrected Example: + +"Don't!" he cried. "You'll ruin the whole thing!"

    + +

    ---5. Fix long dashes (em-dashes) by inserting additional +hyphen character(s) if needed. Proofread these as two hyphens +if the em-dash is short and four hyphens if the em-dash is long. If a +line ends with a dash, move the first word of the following line up to +"clothe the naked dash", then insert a line break following the word +you just moved. See the Proofreading +Guidelines for more details.

    +

    Scan Example: +
    He walked over to the window-a strange look on his face- +
    and tapped on the glass. "Susan!---- Over here!" +

    Corrected Example: +
    He walked over to the window--a strange look on his face--and +
    tapped on the glass. "Susan!----Over here!"

    + +

    ---6. If you have a page with a poem on it, read the Proofreading +Guidelines, to see how to handle it. Set it off from surrounding +text by inserting one blank line before and one blank line after the poem; +it is not necessary to preserve indentation or attempt to center lines.

    + +

    ---7. Italics?, Small Caps? or Bold? If the text you are proofing +includes italics mark-up (<i> and +</i>), small caps mark-up (<sc> and + +</sc>) or bold mark-up (<b> +and </b>) please leave the mark-up for the formatters to review +and correct. Proofers are NOT expected to add or correct this mark-up.

    + +

    ---8. Page Headers and Footers: Running headers/footers may include book +title, author, chapter title, and/or page number. They will be at the very top or +bottom of the page. Remove these, including the page numbers. See the Proofreading +Guidelines for an example. + +

    ---9. Illustrations? Read the Proofreading +Guidelines! Proof the text of the captions, leaving the caption where it falls +on the page. If the caption text was omitted from the OCR'ed text, please type it in. + +

    --10. Footnotes? Read the Proofreading +Guidelines! Leave the note where it falls on the page, and surround the footnote +marker in the text with square brackets, i.e., [1] or [*]. + + +

    --Most of all--Have fun!

    + +

    SHARING INFORMATION, ASKING QUESTIONS, REPORTING PROBLEMS:

    +

    This site has an internal message system. Your personal page shows how many +private messages are waiting in your inbox (in the dark green navbar). Please go +to the forums and login to read your private messages from round 2 proofers. If you +have questions that need a more immediate answer, please click on the "discuss this +project" link above. That will take you to a forum thread that is specific to this project +where you can see what other new people have asked and can get reasonably quick +responses from experienced proofers. There are also several other forums that you +may use to ask questions or make comments that are not project-specific, and still +others designed for amusement.

    + +

    This book scanned and OCR'd pretty cleanly, but if you notice recurring OCR errors, +please post a message in the discussion forum (as described above). That way, we will be +alert for them in post-processing.

    + +

    THANK YOU FOR VOLUNTEERING AT DP, AND FOR YOUR WORK ON THIS BOOK!

    diff --git a/c/pinc/templates/comment_files/BGr2.txt b/c/pinc/templates/comment_files/BGr2.txt new file mode 100644 index 0000000..1dda247 --- /dev/null +++ b/c/pinc/templates/comment_files/BGr2.txt @@ -0,0 +1,5 @@ +

    Thanks to all the new volunteers who have worked on this book. This book has changed from a BEGINNERS ONLY project to a MENTORS project.

    + +

    SECOND ROUND PROOFERS: Please be aware that I promised our new volunteers that "experienced proofers will do a second round. They will send you some friendly suggestions if you are making any obvious beginner mistakes." Remember that formatting issues, with only a very few exceptions, are now being handled in subsequent rounds. Please help by sending feedback and words of encouragement!

    + +

    NOTE:You can find a list of which beginner has done which page, and the number of pages proofed by each, at the For Mentors page.

    \ No newline at end of file diff --git a/c/pinc/templates/comment_files/ammu.txt b/c/pinc/templates/comment_files/ammu.txt new file mode 100644 index 0000000..92cb923 --- /dev/null +++ b/c/pinc/templates/comment_files/ammu.txt @@ -0,0 +1,28 @@ +

    Regarding receipts:

    + +

    The receipts are simple to do. Put one blank line between each receipt, +don't bother to indent (the blank line is sufficient) and mark each donation +amount with a ... before it.

    + +

    Example:

    + +
    RECEIPTS FOR MAY, 1889.
    +
    +MAINE, $352.06.
    +
    +Acton. Cong. Ch. and Soc. ...$3.50
    +
    +Albany. Anna K. Cummings,
    +  for Mountain Work ...2.00
    +
    +Bangor. First Cong. Ch. and Soc. ...38.00
    +
    +Bath. Winter St. Ch. ...140.30
    +
    +Bucksport. Y.P.S.C.E., by Charlotte
    +  S. Barnard, for Pleasant Hill, Tenn. ...20.00
    +
    +Castine. Prof. Fred. W. Foster ...1.44
    + +

    Also, see the UberProjects thread in the forum for questions +and answers.

    diff --git a/c/pinc/templates/comment_files/bae1.txt b/c/pinc/templates/comment_files/bae1.txt new file mode 100644 index 0000000..5417ae6 --- /dev/null +++ b/c/pinc/templates/comment_files/bae1.txt @@ -0,0 +1,7 @@ +

    BAE projects have two special rules that always apply, whether or not the general Guidelines currently say the same thing:
    +* Preserve the page numbers in index, tables of contents, etc.
    +* Preserve information about all diacritical marks, sub-/superscripts and other special characters. Where possible, use the forms shown in the Proofing or Formatting Guidelines.

    + +

    For more information about BAE projects, see the Uber-Project thread.

    + +

    For everything else, refer to the Proofreading Guidelines and Formatting Guidelines.

    \ No newline at end of file diff --git a/c/pinc/templates/comment_files/bell.txt b/c/pinc/templates/comment_files/bell.txt new file mode 100644 index 0000000..a83e010 --- /dev/null +++ b/c/pinc/templates/comment_files/bell.txt @@ -0,0 +1,7 @@ +

    +To the post-processor: +An HTML edition of this is required. Information about the HTML style you +should follow will be given on the overall discussion +thread for this project. Please note that you should be comfortable with +manipulating images. diff --git a/c/pinc/templates/comment_files/bem1.txt b/c/pinc/templates/comment_files/bem1.txt new file mode 100644 index 0000000..2bec8df --- /dev/null +++ b/c/pinc/templates/comment_files/bem1.txt @@ -0,0 +1,42 @@ +

    Blackwood's Edinburgh Magazine

    + +

    Published monthly from April 1817 to December 1980, in Edinburgh +and London, and later in New York, BEM was a mixture of political and +social commentary, and fiction. Many writers had their first work +published in Blackwood's.

    + +

    The images used for this project have been harvested from the +Internet Library of Early Journals (ILEJ). The collection +covers the period January 1843 to December 1863.

    + + +

    Proofing

    + +

    Misspelling in the image should not be changed. Add a [**spelling] +tag to draw PP attention.

    + +

    Please retain all æ ligatures. The œ should be coded as +[OE] or [oe].

    + +

    Refer to the Proofreading +Guidelines for anything else.

    + + +

    Formatting

    + +

    The individual articles of the magazine are to be treated as +chapters, so 4 blank lines before title, and two after. Other +divisions are to be formatted with two lines before titles, and one +after.

    + +

    Refer to the Formatting +Guidelines for anything else.

    + +

    General

    + +

    Please leave notes to the PP that were left by the previous +proofers/formatters.

    + diff --git a/c/pinc/templates/comment_files/diac.txt b/c/pinc/templates/comment_files/diac.txt new file mode 100644 index 0000000..c458eaa --- /dev/null +++ b/c/pinc/templates/comment_files/diac.txt @@ -0,0 +1,18 @@ + +
    +diacritical mark           above  below
    +--------------------------   ------  ------
    +macron (straight line)       [=x]   [x=]
    +2 dots (diaresis or umlaut)  [:x]   [x:]
    +1 dot                        [.x]   [x.]
    +grave accent                 [\x]   [x\]
    +acute (�gu) accent           [/x]   [x/]
    +circumflex                   [^x]   [x^]
    +caron (v-shaped symbol)      [vx]   [xv]
    +breve (u-shaped symbol)      [)x]   [x)]
    +tilde                        [~x]   [x~]
    +cedilla                      [,x]   [x,] 
    +
    + +

    If the diacritical mark is in Latin-1 (i.e. available from the +pulldown list), enter it as one character. diff --git a/c/pinc/templates/comment_files/eets.txt b/c/pinc/templates/comment_files/eets.txt new file mode 100644 index 0000000..8b03a83 --- /dev/null +++ b/c/pinc/templates/comment_files/eets.txt @@ -0,0 +1,26 @@ +

    Additional Proofing Guidelines for this project

    + +

    There are several special characters in these works. So far:
    +
    +The eth (/) and thorn (/) are found in the drop-down boxes.
    +[gh] for the yogh and [Gh] for the capital yogh (it looks like a three),
    +[l~l] for ll with a tilde through them,
    +[h-] for the h with a line through the top,
    +[m~] for a m with a loop back over the character,
    +[n)] for a n with a ) attached to the right side,
    +[rh] for an r with a upwards hook attached to the horizontal stem,
    +[-] for the thorn with a slash through the neck,
    +[et] for the Tironian sign et, which looks like a 7 with the baseline through the middle, possibly with a hook at the bottom (it was replaced with the ampersand in modern writing),
    +[;] for an upside down semicolon,
    +[d+] for the d with a little crook attached to the top right of the d,
    +[s] for the long s (like an f without a crossbar, or with an incomplete crossbar. (This is a change to the standard guidelines.)

    + +

    Use the standard extended characters where necessary.

    + +

    There are many italicized letters in words, to note abbreviations that were expanded. Be sure to mark them. Put sidenotes before the first line they appear on.

    + +

    Mark the headers, except for the page numbers, as sidenotes, as they frequently hold information not on the page.

    + +

    The Uberproject

    + +

    The Early English Text Society is an organization dedicated to printing early English manuscripts, usually but not always Old or Middle English. It was the first organization to print many important manuscripts, including the Pearl, and there are over a hundred volumes printed by them now in the public domain in the United States. We have an Uberproject thread.

    diff --git a/c/pinc/templates/comment_files/grw0.txt b/c/pinc/templates/comment_files/grw0.txt new file mode 100644 index 0000000..2574bee --- /dev/null +++ b/c/pinc/templates/comment_files/grw0.txt @@ -0,0 +1,10 @@ +Please mark Small Caps as < sc > < /sc > (spaces added for display purposes).
    +Please use the block quote markers /# and #/ around the body of letters (in the Letters to the Editor section) and /* */ around the signatures, preserving relative spacing as much as possible. +

    +There are some pages of advertisements at the beginning and end of most issues. Many of these ads repeat from one issue to the next. Please check the uber-project thread to see if the ad on your page has been posted there. If it has, you can just copy the text from the thread, but be sure to check against the image for any subtle changes. If it hasn't been posted, please proof it carefully and then post it. +

    +These issues are from 1897. This is "A Weekly Magazine for Boys and Girls". The LoC search shows that it was published from 1896-1903. I have all of 1897, except for January, plus a few issues from 1898. +

    +The post-processor must make an illustrated html version. High-quality, cropped versions of the illustrations will be found in the images zip file. There are only 2-3 illustrations per issue, along with a couple of variations of the masthead. +

    +Have fun! diff --git a/c/pinc/templates/comment_files/jon1.txt b/c/pinc/templates/comment_files/jon1.txt new file mode 100644 index 0000000..3bbe7ca --- /dev/null +++ b/c/pinc/templates/comment_files/jon1.txt @@ -0,0 +1,20 @@ +

    +To the post-processor: +An HTML edition of this is required. We don't yet have any set standards for +HTML, although these are being developed. In the mean time, make sure that +whatever you produce satisfied the following: +

      +
    • Please make sure that the HTML validates to at least XHTML 1.0 +transitional. +
    • Anchors should be made named 'pageXXX', enabling the reader to jump +straight to a particular page. +
    • If the project has an index, then this index should be formatted as a +nested list, and the page numbers listed should be linked to the page anchors +you've already created. +
    • Edition and printing information should be retained. +
    • Please check the list of images (follow the 'View Images Online' link on +the post-processing page). Any illustrations will have been scanned in +seperately in grayscale or colour, and will generally have been named +imageXX.png. These images should be incorporated into the final HTML +edition. +
    diff --git a/c/pinc/templates/comment_files/nar2.txt b/c/pinc/templates/comment_files/nar2.txt new file mode 100644 index 0000000..259f671 --- /dev/null +++ b/c/pinc/templates/comment_files/nar2.txt @@ -0,0 +1,127 @@ +

    This is a second-time for this text to be proofed. Many small errors +remained after the normal 2 rounds of proofing, so we are trying to +eliminate them prior to post processing.

    +

    Two common reasons for these remaining errors are:

    +
      +
    • The images are copies (of copies of...) typewritten material. They +are difficult to see unless you proof with at least 100% zoom.
    • +
    • The vernacular means you cannot assume anything about a word's +spelling. Reading is not sufficient, you have to compare to the image. Many +people are finding it best to start at the bottom and work backwards so +they do not get trapped by reading such interesting content.
    • +
    + +
    +
    +
    Interview Headers:

    +
    At start of an interview leave four blank lines,
    + /*
    + one item per line
    + one item per line
    + */
    + two blank lines,
    + then start the interview.
    +
    +
    Handwritten Comments:

    +
    If spelling or punctuation was corrected in + handwriting, simply make the correction. If, however, a word or phrase + was added insert it like [HW: this ] or if a question mark was + inserted mark it[HW:?]. +
    +
    Transcriber's Comments:

    +
    + If, for example, a sentence was begun but not + completed you would [TR: sentence unfinished]. Or if a word was + illegible you would mark it [TR: illegible] or if you're not sure of + it 1883[TR:?]. That's a Transcriber's Comment done by you, as opposed + to a Handwritten Comment done by an editor. +

    +Please be careful about removing any Transcriber's Comments in +second round. They are not difficult to remove in PP and, in general, are +helpful. If you're doing second round and want to add a comment, that's great. +
    +
    Typos, Misspellings in the original +document:

    +
    + You will encounter many of these. The post-processor + will have to make decisions on what to correct and what to leave as is + based on many factors. If definitely not part of dialect, mark + such words with * to be sure they're noticed. +
    +
    Difficult to spot errors from the +OCR:

    +
    +
      +
    • "Stealth Scannos": For example, "He" and "We" are both valid words +often mistaken for each + other when the OCR interpreted the typewriter print. "Dey" or +"dey" (dialect for "they") is often + presented as "day" from the OCR software. Look very carefully at +the scans while you are + proofing. Only people can find these! +
    • +
    • Dialect: You will find examples of both "wuz" and "waz", and +"chillun" and "chillen"; only + a careful check against the scan can tell you which is used in any +one instance. +
    • +
    • Check carefully for "1"/"l"/"I"/"!" (digit-one / +lower-case-ell / upper-case-eye / exclamation-mark) + and "0"/"O"/"o" (digit-zero / upper-case-oh / lower-case-oh). + They look alike in some fonts, but don't be fooled. "0h!" is *not* +a word ... fix it to be "Oh!" + "We'!1" shoud be "We'll". +
    • +
    • The OCR commonly mistook the letter B (upper-case B) for a + "B (double-quote, upper-case B). Please keep an eye out for this. +
    • +
    • Some combinations of letters are more likely to have been +missed in the first proofing + rounds. Combinations that tend to misscan:
      + Kl→KL, li→ll, ch→oh, rn↔m
    • +
    • Some individual scannos that were often missed in the first +proofing rounds are:
      + e↔a, e↔s, s→a, c↔o, h→n, +M↔N, H↔M, W→v, W→w, I→i
    • +
    • Perhaps because of so many dialect words, another commonly +missed problem was a missing "i", e.g. "takng" +
    • +
    +
    +
    Punctuation:

    +
    +
      +
    • Comma/period errors, especially commas at ends of sentences.
    • +
    • Extra comma next to period.
    • +
    • Periods sometimes scan as "^".
    • +
    • Extraneous quote marks may appear before letters with leading +lines, like "W" or "N".
    • +
    • Watch quotes in general, also check single/double quote +match-ups.
    • +
    • Apostrophes ("'") sometimes scan as "l" or "f", e.g. "Ilse" +should be "I'se".
    • +
    • Exclamation marks ("!") often scan as lower-case-ell ("l") or +digit-one ("1").
    • +
    +
    +
    Underlines:

    +
    + A few instances of acutual underlining appear in the text. Mark words +underlined for emphasis + "<u>word</u>". +Sometimes it looks like someone just randomly underlined words on a page ... + reading with a pencil trailing. Don't keep these underlines. +
    +
    Initials:

    +
    + If two upper-case initials separated put them together, e.g. "A.H. Jones" +
    +
    New Paragraph at start of page:

    +
    + If you don't mind, you can do something that will be helpful in post +processing. + If the first line on the page is definitely a new paragraph, add a blank +line before it. +
    +
    \ No newline at end of file diff --git a/c/pinc/templates/comment_files/pgnm.txt b/c/pinc/templates/comment_files/pgnm.txt new file mode 100644 index 0000000..db19078 --- /dev/null +++ b/c/pinc/templates/comment_files/pgnm.txt @@ -0,0 +1,3 @@ + +

    PLEASE PRESERVE THE PAGE NUMBERS IN THE INDEX

    +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/c/pinc/templates/comment_files/port.txt b/c/pinc/templates/comment_files/port.txt new file mode 100644 index 0000000..f46646b --- /dev/null +++ b/c/pinc/templates/comment_files/port.txt @@ -0,0 +1,14 @@ +

    Please keep the original spelling. The OCR software has incorrectly "updated" some of the words.

    + +

    Use the new guidelines for footnotes. Mark them as [1], [2], ... in the text. In the place of the page where you find the footnote text write [Footnote 1: text of footnote]

    + +
    + +

    Por favor conserve a ortografia original. O software de reconhecimento de caracters "actualizou" incorrectamente algumas palavras.

    + +

    Use as novas regras para revis�o de notas de rodap�. Marque-as como [1], [2], ... no texto. No local onde est� o texto da nota de rodap� escreva [Footnote 1: texto da nota de rodap�]

    + +
    + +

    Images and OCR supplied by the National Library of Portugal's Digital National Library project.

    + diff --git a/c/pinc/templates/comment_files/samp.txt b/c/pinc/templates/comment_files/samp.txt new file mode 100644 index 0000000..e538e4c --- /dev/null +++ b/c/pinc/templates/comment_files/samp.txt @@ -0,0 +1 @@ +[BLANK] \ No newline at end of file diff --git a/c/pinc/templates/comment_files/ted0.txt b/c/pinc/templates/comment_files/ted0.txt new file mode 100644 index 0000000..ab6758b --- /dev/null +++ b/c/pinc/templates/comment_files/ted0.txt @@ -0,0 +1,19 @@ +

    Please retain page references (like see page number x, or the page numbers +in the Table of Contents or Index), not actual page numbers at the top or +bottom of the page. +

    Please make a HTML edition, including any illustrations, if +any. +

    Formatting is important; please format TOCs, lists of Illustrations, +etc., correctly. +

    Render the OE/oe ligature as [OE] or [oe], as appropriate. Also, keep all +ligatures if they are present in the text. +

    Please note any problems, observations, complains, request +for guidance etc., in that forum. There, we will reach +consensus and make a decision. +

    Please EMAIL me with any problems (missing pages and the like) you may +have. I check my email several times per day and usually respond within 24 +hours. +

    I apologize in advance for any missing pages or other difficulties. +If you encounter such, please post to the Missing Pages Wiki as well as making +a note in the appropriate forum and emailing me. +- Ted diff --git a/c/pinc/templates/comment_files/wrrn.txt b/c/pinc/templates/comment_files/wrrn.txt new file mode 100644 index 0000000..7f9337c --- /dev/null +++ b/c/pinc/templates/comment_files/wrrn.txt @@ -0,0 +1,163 @@ +

    Last updated: 2004-03-26 (see changelog)

    + +

    Contents

    + +

    Use the links to skip to the section of your choice (or scroll as desired).

    + + + +

    Keep Text as Close to Original as +Possible!

    + +

    We've had some mention of people changing things like "* * *" to "..." – +Please do not make such substitutions! Please keep all text as +close to the original as possible. + +

    Copyrighted Materials

    + +

    Some of the content in the Warren Report and its supporting evidentiary and +testimonial volumes is still under copyright. As a result, we are not allowed to +include this copyrighted material in Project Gutenberg. Most (if not all) of this +material has been identified, and place-holders have been included in the page +images to indicate where these copyrighted materials occur.

    + +

    If you come across any materials (e.g., photographs, movie stills, etc.) that you +think may need to be removed, please post a comment in the project thread.

    + +

    Crossed-Out Words

    + +

    In some places, words have been crossed out, removed, or redacted in some other +way. Please mark these in one of the following two ways:

    + +
      +
    • If the word is readable, please print the word and put a note after it like, +[**word crossed out]
    • +
    • If it is not readable, please just put a [**note] where it occurs.
    • +
    + +

    Dashes

    + +

    Recently the Proofing Guidelines changed so that all dashes are now represented +by two hyphens (--). However, in the testimony, it is very clear that some +dashes are longer than others. For longer dashes, please use four hyphens +(----).

    + +

    Note that hyphens should still have only one hyphen (-).

    + +

    Dialogue

    + +

    The testimonial volumes are primarily dialogue. Please mark the speaker's names +as bold (i.e., with <b> and </b> tags), like so:

    + +
    <b>Mr. RANKIN.</b> Mrs. Oswald, did you write in Russian a story of
    +your experiences in the United States?
    +
    +<b>Mrs. OSWALD.</b> Yes, I have. I think that you are familiar with
    +it.
    + +

    (Note: Please include the period inside the bold tags.)

    + +

    Forms

    + +

    The Commission Exhibits contain quite a few forms. The important thing when +transcribing these forms is to get the information out of them; layout is not that +important (except in some cases where the form might contain tabular data).

    + +

    There is an example in the Warren Commission UberProject thread on how forms can +be transcribed: http://www.pgdp.net/phpBB2/viewtopic.php?p=62370#62370

    + +

    Grayscale Images

    + +

    Each text file in the Evidence volumes (XVI-XXVI) has a URL a grayscale image for +that page. These URLs are there for your reference, to help you identify portions +that may not be clear in the black & white version of the page.

    + +

    The grayscale images are hosted by Pluckerbooks.com. Pluckerbooks runs off +d.maddock1's cablemodem connection, so please be nice. Also, because d.maddock1's +ISP blocks port 80 (the standard HTTP port), the site runs off port 81, which means +you may have trouble accessing the images from behind a firewall and/or proxy.

    + +

    Non-Standard Formatting

    + +

    Many of the exhibits (which are given in the later volumes) are things like forms +and charts which will be very hard to format using only ASCII text. We just ask +that you do your best. Don't worry about trying to make sure all the lines are +exact – it's the text and meaning of the documents that are important.

    + +

    Underlined Text

    + +

    Some of the Commission Exhibits contain documents that have underlined text. The +Proofing Guidelines say to mark underlined text similarly to italicized text; +however, we would like for this project to have underlined text +marked with <u< and </u< tags. For example: + +

      Here is some underlined text.
    + +

    Should be marked as:

    + +
      Here is some <u>underlined</u> text.
    + +

    Anything Else

    + +

    Please jump over to the forums if you have any questions about anything else.

    + + + +
    + +

    wrrn.txt Changelog

    + +

    Below is a history of changes made to this set of notes.

    + +
    +

    2004-03-26

    +
      +
    • Added notes on Form and link to example
    • +
    • Removed following sections that applied to the Report only: Image Captions, +Footnotes, Superscripts +
    • Reorganized sections
    • +
    • Added linked TOC to sections
    • +
    • Created changelog
    • +
    +
    diff --git a/c/pinc/templates/default_graphics/tabs_left.png b/c/pinc/templates/default_graphics/tabs_left.png new file mode 100644 index 0000000..7e3a511 Binary files /dev/null and b/c/pinc/templates/default_graphics/tabs_left.png differ diff --git a/c/pinc/templates/default_graphics/tabs_left_on.png b/c/pinc/templates/default_graphics/tabs_left_on.png new file mode 100644 index 0000000..aef6ec4 Binary files /dev/null and b/c/pinc/templates/default_graphics/tabs_left_on.png differ diff --git a/c/pinc/templates/default_graphics/tabs_right.png b/c/pinc/templates/default_graphics/tabs_right.png new file mode 100644 index 0000000..1c5eea1 Binary files /dev/null and b/c/pinc/templates/default_graphics/tabs_right.png differ diff --git a/c/pinc/templates/default_graphics/tabs_right_on.png b/c/pinc/templates/default_graphics/tabs_right_on.png new file mode 100644 index 0000000..0a8eb86 Binary files /dev/null and b/c/pinc/templates/default_graphics/tabs_right_on.png differ diff --git a/c/pinc/templates/project_gutenberg/graphics/donate.gif b/c/pinc/templates/project_gutenberg/graphics/donate.gif new file mode 100644 index 0000000..2ca03ea Binary files /dev/null and b/c/pinc/templates/project_gutenberg/graphics/donate.gif differ diff --git a/c/pinc/templates/project_gutenberg/graphics/dpclogo5.png b/c/pinc/templates/project_gutenberg/graphics/dpclogo5.png new file mode 100644 index 0000000..cb103a1 Binary files /dev/null and b/c/pinc/templates/project_gutenberg/graphics/dpclogo5.png differ diff --git a/c/pinc/templates/project_gutenberg/graphics/l_curve.gif b/c/pinc/templates/project_gutenberg/graphics/l_curve.gif new file mode 100644 index 0000000..fd76e45 Binary files /dev/null and b/c/pinc/templates/project_gutenberg/graphics/l_curve.gif differ diff --git a/c/pinc/templates/project_gutenberg/graphics/logo.gif b/c/pinc/templates/project_gutenberg/graphics/logo.gif new file mode 100644 index 0000000..cb79125 Binary files /dev/null and b/c/pinc/templates/project_gutenberg/graphics/logo.gif differ diff --git a/c/pinc/templates/project_gutenberg/graphics/r_curve.gif b/c/pinc/templates/project_gutenberg/graphics/r_curve.gif new file mode 100644 index 0000000..0a741b5 Binary files /dev/null and b/c/pinc/templates/project_gutenberg/graphics/r_curve.gif differ diff --git a/c/pinc/templates/project_gutenberg/graphics/tabs_bg.png b/c/pinc/templates/project_gutenberg/graphics/tabs_bg.png new file mode 100644 index 0000000..12a4551 Binary files /dev/null and b/c/pinc/templates/project_gutenberg/graphics/tabs_bg.png differ diff --git a/c/pinc/templates/project_gutenberg/graphics/tabs_left.png b/c/pinc/templates/project_gutenberg/graphics/tabs_left.png new file mode 100644 index 0000000..af6150b Binary files /dev/null and b/c/pinc/templates/project_gutenberg/graphics/tabs_left.png differ diff --git a/c/pinc/templates/project_gutenberg/graphics/tabs_left_on.png b/c/pinc/templates/project_gutenberg/graphics/tabs_left_on.png new file mode 100644 index 0000000..d1179b5 Binary files /dev/null and b/c/pinc/templates/project_gutenberg/graphics/tabs_left_on.png differ diff --git a/c/pinc/templates/project_gutenberg/graphics/tabs_right.png b/c/pinc/templates/project_gutenberg/graphics/tabs_right.png new file mode 100644 index 0000000..3a46a1a Binary files /dev/null and b/c/pinc/templates/project_gutenberg/graphics/tabs_right.png differ diff --git a/c/pinc/templates/project_gutenberg/graphics/tabs_right_on.png b/c/pinc/templates/project_gutenberg/graphics/tabs_right_on.png new file mode 100644 index 0000000..91f93bc Binary files /dev/null and b/c/pinc/templates/project_gutenberg/graphics/tabs_right_on.png differ diff --git a/c/pinc/templates/project_gutenberg/main.css b/c/pinc/templates/project_gutenberg/main.css new file mode 100644 index 0000000..74eb086 --- /dev/null +++ b/c/pinc/templates/project_gutenberg/main.css @@ -0,0 +1,4 @@ + +tt { + color: #c00; +} diff --git a/c/pinc/templates/project_gutenberg/theme.tpl b/c/pinc/templates/project_gutenberg/theme.tpl new file mode 100644 index 0000000..278b1c2 --- /dev/null +++ b/c/pinc/templates/project_gutenberg/theme.tpl @@ -0,0 +1,48 @@ + '#e0e8dd', + 'background-position' => 'top', + 'padding-left' => '9px', +); +?> diff --git a/c/pinc/templates/royal_blues/graphics/donate.gif b/c/pinc/templates/royal_blues/graphics/donate.gif new file mode 100644 index 0000000..2ca03ea Binary files /dev/null and b/c/pinc/templates/royal_blues/graphics/donate.gif differ diff --git a/c/pinc/templates/royal_blues/graphics/l_curve.gif b/c/pinc/templates/royal_blues/graphics/l_curve.gif new file mode 100644 index 0000000..8386864 Binary files /dev/null and b/c/pinc/templates/royal_blues/graphics/l_curve.gif differ diff --git a/c/pinc/templates/royal_blues/graphics/logo.gif b/c/pinc/templates/royal_blues/graphics/logo.gif new file mode 100644 index 0000000..e39e0f6 Binary files /dev/null and b/c/pinc/templates/royal_blues/graphics/logo.gif differ diff --git a/c/pinc/templates/royal_blues/graphics/oldlogo.gif b/c/pinc/templates/royal_blues/graphics/oldlogo.gif new file mode 100644 index 0000000..56d6c73 Binary files /dev/null and b/c/pinc/templates/royal_blues/graphics/oldlogo.gif differ diff --git a/c/pinc/templates/royal_blues/graphics/r_curve.gif b/c/pinc/templates/royal_blues/graphics/r_curve.gif new file mode 100644 index 0000000..82a6d14 Binary files /dev/null and b/c/pinc/templates/royal_blues/graphics/r_curve.gif differ diff --git a/c/pinc/templates/royal_blues/graphics/tabs_bg.png b/c/pinc/templates/royal_blues/graphics/tabs_bg.png new file mode 100644 index 0000000..290ab28 Binary files /dev/null and b/c/pinc/templates/royal_blues/graphics/tabs_bg.png differ diff --git a/c/pinc/templates/royal_blues/graphics/tabs_left.png b/c/pinc/templates/royal_blues/graphics/tabs_left.png new file mode 100644 index 0000000..491951f Binary files /dev/null and b/c/pinc/templates/royal_blues/graphics/tabs_left.png differ diff --git a/c/pinc/templates/royal_blues/graphics/tabs_left_on.png b/c/pinc/templates/royal_blues/graphics/tabs_left_on.png new file mode 100644 index 0000000..2cbe641 Binary files /dev/null and b/c/pinc/templates/royal_blues/graphics/tabs_left_on.png differ diff --git a/c/pinc/templates/royal_blues/graphics/tabs_right.png b/c/pinc/templates/royal_blues/graphics/tabs_right.png new file mode 100644 index 0000000..9d70a8c Binary files /dev/null and b/c/pinc/templates/royal_blues/graphics/tabs_right.png differ diff --git a/c/pinc/templates/royal_blues/graphics/tabs_right_on.png b/c/pinc/templates/royal_blues/graphics/tabs_right_on.png new file mode 100644 index 0000000..c43ddf1 Binary files /dev/null and b/c/pinc/templates/royal_blues/graphics/tabs_right_on.png differ diff --git a/c/pinc/templates/royal_blues/main.css b/c/pinc/templates/royal_blues/main.css new file mode 100644 index 0000000..74eb086 --- /dev/null +++ b/c/pinc/templates/royal_blues/main.css @@ -0,0 +1,4 @@ + +tt { + color: #c00; +} diff --git a/c/pinc/templates/royal_blues/theme.tpl b/c/pinc/templates/royal_blues/theme.tpl new file mode 100644 index 0000000..849cb1c --- /dev/null +++ b/c/pinc/templates/royal_blues/theme.tpl @@ -0,0 +1,48 @@ + '#ffffff', + 'background-position' => 'top', + 'padding-left' => '9px', +); +?> \ No newline at end of file diff --git a/c/pinc/templates/theme.tpl b/c/pinc/templates/theme.tpl new file mode 100644 index 0000000..278b1c2 --- /dev/null +++ b/c/pinc/templates/theme.tpl @@ -0,0 +1,48 @@ + '#e0e8dd', + 'background-position' => 'top', + 'padding-left' => '9px', +); +?> diff --git a/c/pinc/theme.inc b/c/pinc/theme.inc new file mode 100644 index 0000000..ea915cb --- /dev/null +++ b/c/pinc/theme.inc @@ -0,0 +1,662 @@ +Username(); + +include_once($relPath.'gettext_setup.inc'); +//include_once($relPath."templates/theme.tpl"); + +function theme($nameofpage, $location, $extra_args = array()) { + global $User, $code_url; // $theme, $theme_name; + global $no_stats; + + if(! $User->IsLoggedIn()) { + $no_stats = 1; + } + + $statsbar_align = "right"; + + if (! $no_stats) { + // if stats bar on left + if ($statsbar_align == "left") { + + if ($location == "header") { + +/* + ------------------------------------------------- + header when NOT $no_stats and stats bar on left + ------------------------------------------------- +*/ + + html_header($nameofpage, $extra_args); + html_logobar($nameofpage); + echo " + + + + +
    + Provides a round curve for a navigation bar\n"; + } + +// ------------------------------------------------- +// footer when NOT $no_stats and stats bar on left +// ------------------------------------------------- + + else if ($location == "footer") { + echo "
    \n"; + html_footer(); + } + } + else { + if ($location == "header") { + +// ------------------------------------------------- +// header when NOT $no_stats and stats bar on right +// ********** MOST COMMON CASE *************** +// ------------------------------------------------- + + html_header($nameofpage, $extra_args); + html_logobar($nameofpage); + echo " + + + + +
    \n"; + } + +// ------------------------------------------------- +// footer when NOT $no_stats and stats bar on right +// ------------------------------------------------- + + else if($location == "footer") { + echo " + + +
    \n"; + html_footer(); + } + } + } + else { + // is no_stats + if ($location == "header") { + +// ----------------------------------------------------- +// header when IS $no_stats so no stats bar to position +// ----------------------------------------------------- + + html_header($nameofpage, $extra_args); + html_logobar($nameofpage); + echo " + + + +
     \n"; + } + else if($location == "footer") { + +// ----------------------------------------------------- +// footer when IS $no_stats so no stats bar to position +// ----------------------------------------------------- + + echo "
    \n"; + html_footer(); + } + } +} + +function html_header($nameofpage, $extra_args = array()) { + global $code_url; + + $incl = ""; + $onload = ""; + foreach($extra_args as $key => $val) { + switch($key) { + case "hdr_include": + break; + + case "css_file": + $incl .= "\n"; + break; + + case "css_data": + $incl .= "\n"; + break; + + case "js_text": + case "js_data": + $incl .= "\n"; + break; + + case "js_file": + $incl .= "\n"; + break; + + case "body_onload": + $onload .= " onload='$val'"; + break; + } + } + + echo +" + + + + +\n"; + +echo " + +DPC: ". (isset($nameofpage) + ? "$nameofpage" + : "Distributed Proofreaders Canada" ) +. " +\n"; + echo +"$incl + +\n"; +} + +function html_logobar() { + global $code_url; + global $dpdb; + global $User; + +// $username = $User->Username(); + $numproj = $dpdb->SqlOneValue(" + SELECT COUNT(distinct postednum) FROM projects + WHERE phase = 'POSTED'"); + + echo " + + + + + + + + + +
    + + Distributed Proofreaders + + + + " . sprintf( _('%s titles preserved for the world!'), number_format($numproj)) ." + +
    \n"; + + // -------------------------------------------------------------------- + // navbar + // -------------------------------------------------------------------- + + $divider = " · "; + + echo " + +
    + + + + + \n"; + } + else { + $items = array( link_to_site("DPC")); + $items[] = link_to_activity_hub(); + $items[] = link_to_search("Project Search"); + $items[] = link_to_my_projects(); + $items[] = link_to_preferences(); + + $inbox_text = _("My Inbox"); + $numofPMs = $User->InboxCount(); + if($numofPMs[0] > 0) { + $inbox_text .= sprintf(_(" (%s unread)"), $numofPMs[0]); + } + $items[] = link_to_inbox($inbox_text); + $items[] = link_to_forums(); + $items[] = link_to_wiki(); + $items[] = link_to_logout("Log out ({$User->Username()})"); + + echo implode($divider, $items); + + echo "\n"; + + echo ""; + } + + + echo "\n"; + echo "
     \n"; + + if (! $User->IsLoggedIn()) { + $link_to_forums_login = "Forums"; + $items = array( link_to_site("DPC")); + $items[] = $link_to_forums_login; + echo implode($divider, $items); + echo " + ID: + +  " . _("Password:") . " +   + \n"; + echo link_to_registration(); + echo "  + \n"; + show_quick_links(); + echo " 
    \n"; + echo "
    \n"; +} + +function login_form() { + global $code_url; + $password = _("Password: "); + $signin = _("Sign In: "); + return " +
    + ID: + + $password + + \n" + . link_to_registration() + . link_to_help() + . "
    \n"; +} + +//function headerbar_text($text, $link = '', $with_divider = false) { +// $out = ""; +// +// if ($with_divider) { +// $out .= " · "; +// } +// +// if(!empty($link)) { +// $out .= "$text\n"; +// } +// else { +// $out .= $text; +// } +// +// return $out; +//} + +function html_statsbar() { + global $User; + global $code_url; + global $pagename; + + // Show statistics that are pertinent to the particular request. + // (i.e., to the main content of the page). + + if(isset($pagename) && $pagename == "activityhub") { + // show_backlogs(); + } + $round_id = Arg('round_id', Arg('tally_name')); + + if($round_id == "") { + show_completed_projects(); + } + else { + show_round_specific_stats( $round_id ); + } + + if($User->IsLoggedIn()) { + echo " + \n"; + + + echo "
    \n"; + show_user_teams(); + + echo "
    \n"; + show_key_help_links(); + echo "
    \n"; + } +} + +// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + +/* +function maybe_show_language_selector() { + global $code_url, $intlang; + $instl=installed_langs(); + $uninstl=uninstalled_langs(); + if(!(count($instl)>1||count($uninstl)>0)) + return; + + if (empty($userP) || (!(empty($userP)) && !($userP['u_intlang']))) { + ?> + + \n\n\n\n"; + echo "Languages below the line are planned to be added to the site, but currently are not; visit this page if you can help us with translating the site into one of them.
    \n"; + } +} +*/ + +// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + +// This parallels the Activity Hub. +function show_quick_links() { + global $User; + + if (! $User->IsLoggedIn()) + return; + + $items = array(); + + if ($User->IsProjectManager() || $User->IsSiteManager()) { + $items[] = link_to_project_manager("PM"); + } + +// foreach(array("P1", "P2", "P3", "F1", "F2", "PP", "PPV") as $phs) { + foreach(array("P1", "P2", "P3", "F1", "F2") as $phs) { + if($User->MayWorkInRound($phs)) { + $items[] = link_to_round($phs); +// $title = PhaseCaption($phs); +// $link = link_to_round($phs); +// echo headerbar_text("$text", "$code_url/$rel_url", $divider); +// $links[] = array(link_to_round($phs), $phs, $phs); + } + } + if($User->MayWorkInRound("PP")) { + $items[] = link_to_pp(); + } + if($User->MayWorkInRound("PPV")) { + $items[] = link_to_ppv(); + } + $items[] = link_to_smooth_reading("SR"); + + $divider = "\n · "; + echo implode($divider, $items); + +// if ( count($links) > 0 ) { +// while ( list($i, list($rel_url, $text, $title)) = each($links) ) { +// $divider = ($i > 0) +// ? true +// : false; +// +// echo headerbar_text("$text", "$code_url/$rel_url", $divider); +// echo "\n"; +// } +// } +} + +// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + +function show_round_specific_stats( $round_id ) { + global $User; + + // Put the whole thing in a table, just so we can put a box around it. + echo " + + + "; +} + +function honorific_for_count($round_id, $count) { + global $Honorifics; + $dignity = "Novice"; + foreach($Honorifics[$round_id] as $key => $value) { + $dignity = $value; + if($count < $key) { + break; + } + } + return $dignity; +} + +function ename($name) { + global $User; + return $name == $User->Username() + ? "$name" + : $name; +} + +// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + +function show_user_teams() +{ + global $code_url; + global $dpdb; + global $User; + + $rows = $dpdb->SqlRows(" + SELECT teamname, id FROM user_teams + WHERE id IN ({$User->Team1()}, {$User->Team2()}, {$User->Team3()})"); + + echo " + \n"; +} + +// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + + +function show_completed_projects() { + global $dpdb; + + echo _("
    Completed Projects:
    \n"); + echo "\n"; + $rows = $dpdb->SqlRows(" + SELECT COUNT(1) c, MONTH(d) m, MONTHNAME(d) mname, YEAR(d) y + FROM ( + SELECT FROM_UNIXTIME(event_time) d + FROM project_events pe + WHERE event_type = 'post' + AND event_time > + UNIX_TIMESTAMP( DATE( DATE_FORMAT( + DATE_ADD( CURRENT_DATE(), INTERVAL -1 YEAR), '%Y-%m-01'))) + ) tbl + GROUP BY m, y + ORDER BY y, m"); + + foreach($rows as $row) { + $displaydate = "{$row['mname']} {$row['y']}"; + echo " + + + \n"; + } + echo "\n"; +} + +// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + +function show_key_help_links() { + global $wiki_url; + + echo " + \n"; +} + +function show_backlogs() { + echo " +