The process of generating an index usually involves three steps:
Code the index entries in the document.
Format the document, producing index entries with page numbers.
Process the index entries to sort them, combining entries that differ only in page number, and then preparing the formatted index.
This process remains pretty much the same whether using troff, other coded batch formatters, or a WYSIWYG formatter such as FrameMaker, although the steps are not as clearly separated with the latter. However, I will be describing how we use troff to generate an index such as the one for this book. We code the index using the following macros:
| Macro | Description |
|---|---|
| .XX | Produces general index entries. |
| .XN | Creates "see" or "see also" cross references. |
| .XB | Creates bold page entry indicating primary reference. |
| .XS | Begins range of pages for entry. |
| .XE | Ends range of pages for entry. |
These macros take a single quoted argument, which can have one of several forms, indicating primary, secondary, or tertiary keys:
"
primary
[ :secondary
[ ;tertiary
]]"
A colon is used as the separator between the primary and secondary keys. To support an earlier coding convention, the first comma is interpreted as the separator if no colon is used. A semicolon indicates the presence of a tertiary key. The page number is always associated with the last key.
Here is an entry with only a primary key:
.XX "XView"
The next two entries specify a secondary key:
.XX "XView: reserved names" .XX "XView, packages"
The most complex entries contain tertiary keys:
.XX "XView: objects; list" .XX "XView: objects; hierarchy of"
Finally, there are two types of cross references:
.XN "error recovery: (see error handling)" .XX "mh mailer: (see also xmh mailer)"
The "see" entry refers a person to another index entry. The "see also" is typically used when there are entries for, in this case, "mh mailer," but there is relevant information catalogued under another name. Only "see" entries do not have page numbers associated with them.
When the document is processed by troff, the following index entries are produced:
XView 42 XView: reserved names 43 XView, packages 43 XView: objects; list of 43 XView: objects; hierarchy of 44 XView, packages 45 error recovery: (See error handling) mh mailer: (see also xmh mailer) 46
These entries serve as input to the indexing program. Each entry (except for "see" entries) consists of the key and a page number. In other words, the entry is divided into two parts and the first part, the key, can also be divided into three parts. When these entries are processed by the indexing program and the output is formatted, the entries for "XView" are combined as follows:
XView, 42 objects; hierarchy of, 44; list of, 43 packages, 43,45 reserved names, 43
To accomplish this, the indexing program must:
Sort the index by key and page number.
Merge entries that differ only in the page number.
Merge entries that have the same primary and/or secondary keys.
Look for consecutive page numbers and combine as a range.
Prepare the index in a format for display on screen or for printing.
This is what the index program does if you are processing the index entries for a single book. It also allows you to create a master index, an overall index for a set of volumes. To do that, an awk script appends either a roman numeral or an abbreviation after the page number. Each file then contains the entries for a particular book and those entries are uniquely identified. If we chose to use roman numerals to identify the volume, then the above entries would be changed to:
XView 42:I XView: reserved names 43:I XView: objects; list of 43:I
With multivolume entries, the final index that is generated might look like this:
XView, I:42; II:55,69,75 objects; hierarchy of, I:44; list of, I:43; II: 56 packages, I:43,45 reserved names, I:43
For now, it's only important to recognize that the index entry used as input to the awk program can have a page number or a page number followed by a volume identifier.
Because of the length and complexity of this indexing application,[2] our description presents the larger structure of the program. Use the comments in the program itself to understand what is happening in the program line by line.
[2] The origins of this indexing program are traced back to a copy of an indexing program written in awk by Steve Talbott. I learned this program by taking it apart, and made some changes to it to support consecutive page numbering in addition to section-page numbering. That was the program I described in UNIX Text Processing. Knowing that program, I wrote an indexing program that could deal with index entries produced by Microsoft Word and generate an index using section-page numbering. Later, we needed a master index for several books in our X Window System Series. I took it as an opportunity to rethink our indexing program, and rewrite it using nawk, so that it supports both single-book and multiple-book indices. The AWK Programming Language contains an example of an index program that is smaller than the one shown here and might be a place to start if you find this one too complicated. It does not, however, deal with keys. That indexing program is a simplified version of the one described in Bell Labs Computing Science Technical Report 128, Tools for Printing Indexes, October 1986, by Brian Kernighan and Jon Bentley. [D.D.]
After descriptions of each of the program modules, a final section discusses a few remaining details. For the most part, these are code fragments that deal with nitty-gritty, input-related problems that had to be solved along the way. The shell script masterindex[3] allows the user to specify a number of different command-line options to specify what kind of index to make and it invokes the necessary awk programs to do the job. The operations of the masterindex program can be broken into five separate programs or modules that form a single pipe.
[3] This shell script and the documentation for the program are presented in Appendix C. You might want to first read the documentation for a basic understanding of using the program.
input.idx | sort | pagenums.idx | combine.idx | format.idx
All but one of the programs are written using awk. For sorting the entries, we rely upon sort, a standard UNIX utility. Here's a brief summary of what each of these programs does:
Standardizes the format of entries and rotates them.
Sorts entries by key, volume, and page number.
Merges entries with same key, creating a list of page numbers.
Combines consecutive page numbers into a range.
Prepares the formatted index for the screen or processing by troff.
We will discuss each of these steps in a separate section.
This input.idx script looks for different types of entries and standardizes them for easier processing by subsequent programs. Additionally, it automatically rotates index entries containing a tilde (~). (See the section "Rotating Two Parts" later in this chapter.)
The input to the input.idx program consists of two tab-separated fields, as described earlier. The program produces output records with three colon-separated fields. The first field contains the primary key; the second field contains the secondary and tertiary keys, if defined; and the third field contains the page number.
Here's the code for input.idx program:
#!/work/bin/nawk -f # ------------------------------------------------ # input.idx -- standardize input before sorting # Author: Dale Dougherty # Version 1.1 7/10/90 # # input is "entry" tab "page_number" # ------------------------------------------------ BEGIN { FS = "\t"; OFS = "" } #1 Match entries that need rotating that contain a single tilde # $1 ~ /~[^~]/ # regexp does not work and I do not know why $1 ~ /~/ && $1 !~ /~~/ { # split first field into array named subfield n = split($1, subfield, "~") if (n == 2) { # print entry without "~" and then rotated printf("%s %s::%s\n", subfield[1], subfield[2], $2) printf("%s:%s:%s\n", subfield[2], subfield[1], $2) } next }# End of 1 #2 Match entries that contain two tildes $1 ~ /~~/ { # replace ~~ with ~ gsub(/~~/, "~", $1) } # End of 2 #3 Match entries that use "::" for literal ":". $1 ~ /::/ { # substitute octal value for "::" gsub(/::/, "\\72", $1) }# End of 3 #4 Clean up entries { # look for second colon, which might be used instead of ";" if (sub(/:.*:/, "&;", $1)) { sub(/:;/, ";", $1) } # remove blank space if any after colon. sub(/: */, ":", $1) # if comma is used as delimiter, convert to colon. if ( $1 !~ /:/ ) { # On see also & see, try to put delimiter before "(" if ($1 ~ /\([sS]ee/) { if (sub(/, *.*\(/, ":&", $1)) sub(/:, */, ":", $1) else sub(/ *\(/, ":(", $1) } else { # otherwise, just look for comma sub(/, */, ":", $1) } } else { # added to insert semicolon in "See" if ($1 ~ /:[^;]+ *\([sS]ee/) sub(/ *\(/, ";(", $1) } }# End of 4 #5 match See Alsos and fix for sort at end $1 ~ / *\([Ss]ee +[Aa]lso/ { # add "~zz" for sort at end sub(/\([Ss]ee +[Aa]lso/, "~zz(see also", $1) if ($1 ~ /:[^; ]+ *~zz/) { sub(/ *~zz/, "; ~zz", $1) } # if no page number if ($2 == "") { print $0 ":" next } else { # output two entries: # print See Also entry w/out page number print $1 ":" # remove See Also sub(/ *~zz\(see also.*$/, "", $1) sub(/;/, "", $1) # print as normal entry if ( $1 ~ /:/ ) print $1 ":" $2 else print $1 "::" $2 next } }# End of 5 #6 Process entries without page number (See entries) (NF == 1 || $2 == "" || $1 ~ /\([sS]ee/) { # if a "See" entry if ( $1 ~ /\([sS]ee/ ) { if ( $1 ~ /:/ ) print $1 ":" else print $1 ":" next } else { # if not a See entry, generate error printerr("No page number") next } }# End of 6 #7 If the colon is used as the delimiter $1 ~ /:/ { # output entry:page print $1 ":" $2 next }# End of 7 #8 Match entries with only primary keys. { print $1 "::" $2 }# End of 8 # supporting functions # # printerr -- print error message and current record # Arg: message to be displayed function printerr (message) { # print message, record number and record printf("ERROR:%s (%d) %s\n", message, NR, $0) > "/dev/tty" }
This script consists of a number of pattern-matching rules to recognize different types of input. Note that an entry could match more than one rule unless the action associated with a rule calls the next statement.
As we describe this script, we will be referring to the rules by number. Rule 1 rotates entries containing a tilde and produces two output records. The split() function creates an array named subfield that contains the two parts of the compound entry. The two parts are printed in their original order and are then swapped to create a second output record in which the secondary key becomes a primary key.
Because we are using the tilde as a special character, we must provide some way of actually entering a tilde. We have implemented the convention that two consecutive tildes are translated into a single tilde. Rule 2 deals with that case, but notice that the pattern for rule 1 makes sure that the first tilde it matches is not followed by another tilde.[4]
[4] In the first edition, Dale wrote, "For extra credit, please send me mail if you can figure out why the commented regular expression just before rule 1 does not do the job. I used the compound expression as a last resort." I'm ashamed to admit that this stumped me also. When Henry Spencer turned on the light, it was blinding: "The reason why the commented regexp doesn't work is that it doesn't do what the author thought. :-) It looks for tilde followed by a non-tilde character... but the second tilde of a ~~ combination is usually followed by a non-tilde! Using /[^~]~[^~]/ would probably work." I plugged this regular expression in to the program, and it worked just fine. [A.R.]
The order of rules 1 and 2 in the script is significant. We can't replace "~~" with "~" until after the procedure for rotating the entry.
Rule 3 does a job similar to that of rule 2; it allows "::" to be used to output a literal ":" in the index. However, since we use the colon as an input delimiter throughout the input to the program, we cannot allow it to appear in an entry as finally output until the very end. Thus, we replace the sequence "::" with the colon's ASCII value in octal. (The format.idx program will reverse the replacement.)
Beginning with rule 4, we attempt to recognize various ways of coding entries - giving the user more flexibility. However, to make writing the remaining programs easier, we must reduce this variety to a few basic forms.
In the "basic" syntax, the primary and secondary keys are separated by a colon. The secondary and tertiary keys are separated by a semicolon. Nonetheless the program also recognizes a second colon, in place of a semicolon, as the delimiter between the secondary and tertiary keys. It also recognizes that if no colon is specified as a delimiter, then a comma can be used as the delimiter between primary and secondary keys. (In part, this was done to be compatible with an earlier program that used the comma as the delimiter.) The sub() function looks for the first comma on the line and changes it to a colon. This rule also tries to standardize the syntax of "see" and "see also" entries. For entries that are colon-delimited, rule 4 removes spaces after the colon. All of the work is done using the sub() function.
Rule 5 deals with "see also" entries. We prepend the arbitrary string "~zz" to the "see also" entries so that they will sort at the end of the list of secondary keys. The pagenums.idx script, later in the pipeline, will remove "~zz" after the entries have been sorted.
Rule 6 matches entries that do not specify a page number. The only valid entry without a page number contains a "see" reference. This rule outputs "see" entries with ":" at the end to indicate an empty third field. All other entries generate an error message via the printerr() function. This function notifies the user that a particular entry does not have a page number and will not be included in the output. This is one method of standardizing input - throwing out what you can't interpret properly. However, it is critical to notify the user so that he or she can correct the entry.
Rule 7 outputs entries that contain the colon-delimiter. Its action uses next to avoid reaching rule 8.
Finally, rule 8 matches entries that contain only a primary key. In other words, there is no delimiter. We output "::" to indicate an empty second field.
Here's a portion of the contents of our test file. We'll be using it to generate examples in this section.
$cat test
XView: programs; initialization 45 XV_INIT_ARGS~macro 46 Xv_object~type 49 Xv_singlecolor~type 80 graphics: (see also server image) graphics, XView model 83 X Window System: events 84 graphics, CANVAS_X_PAINT_WINDOW 86 X Window System, X Window ID for paint window 87 toolkit (See X Window System). graphics: (see also server image) Xlib, repainting canvas 88 Xlib.h~header file 89
When we run this file through input.idx, it produces:
$input.idx test
XView:programs; initialization:45 XV_INIT_ARGS macro::46 macro:XV_INIT_ARGS:46 Xv_object type::49 type:Xv_object:49 Xv_singlecolor type::80 type:Xv_singlecolor:80 graphics:~zz(see also server image): graphics:XView model:83 X Window System:events:84 graphics:CANVAS_X_PAINT_WINDOW:86 X Window System:X Window ID for paint window:87 graphics:~zz(see also server image): Xlib:repainting canvas:88 Xlib.h header file::89 header file:Xlib.h:89
Each entry now consists of three colon-separated fields. In the sample output, you can find examples of entries with only a primary key, those with primary and secondary keys, and those with primary, secondary, and tertiary keys. You can also find examples of rotated entries, duplicate entries, and "see also" entries.
The only difference in the output for multivolume entries is that each entry would have a fourth field that contains the volume identifier.
Now the output produced by input.idx is ready to be sorted. The easiest way to sort the entries is to use the standard UNIX sort program rather than write a custom script. In addition to sorting the entries, we want to remove any duplicates and for this task we use the uniq program.
Here's the command line we use:
sort -bdf -t: +0 -1 +1 -2 +3 -4 +2n -3n | uniq
As you can see, we use a number of options with the sort command. The first option, -b, specifies that leading spaces be ignored. The -d option specifies a dictionary sort in which symbols and special characters are ignored. -f specifies that lower- and uppercase letters are to be folded together; in other words, they are to be treated as the same character for purposes of the sort. The next argument is perhaps the most important: -t: tells the program to use a colon as a field delimiter for sort keys. The "+" options that follow specify the number of fields to skip from the beginning of the line. Therefore, to specify the first field as the primary sort key, we use "+0." Similarly, the "-" options specify the end of a sort key. "-1" specifies that the primary sort key ends at the first field, or the beginning of the second field. The second sort field is the secondary key. The fourth field ("+3") if it exists, contains the volume number. The last key to sort is the page number; this requires a numeric sort (if we did not tell sort that this key consists of numbers, then the number 1 would be followed by 10, instead of 2). Notice that we sort page numbers after sorting the volume numbers. Thus, all the page numbers for Volume I are sorted in order before the page numbers for Volume II. Finally, we pipe the output to uniq to remove identical entries. Processing the output from input.idx, the sort command produces:
graphics:CANVAS_X_PAINT_WINDOW:86 graphics:XView model:83 graphics:~zz(see also server image): header file:Xlib.h:89 macro:XV_INIT_ARGS:46 toolkit:(See X Window System).: type:Xv_object:49 type:Xv_singlecolor:80 X Window System:events:84 X Window System:X Window ID for paint window:87 Xlib:repainting canvas:88 Xlib.h header file::89 XView:programs; initialization:45 XV_INIT_ARGS macro::46 Xv_object type::49 Xv_singlecolor type::80
The pagenums.idx program looks for entries that differ only in page number and creates a list of page numbers for a single entry. The input to this program is four colon-separated fields:
PRIMARY:SECONDARY:PAGE:VOLUME
The fourth is optional. For now, we consider only the index for a single book, in which there are no volume numbers. Remember that the entries are now sorted.
The heart of this program compares the current entry to the previous one and determines what to output. The conditionals that implement the comparison can be extracted and expressed in pseudocode, as follows:
PRIMARY = $1 SECONDARY = $2 PAGE = $3 if (PRIMARY == prevPRIMARY) if (SECONDARY == prevSECONDARY) print PAGE else print PRIMARY:SECONDARY:PAGE else print PRIMARY:SECONDARY:PAGE prevPRIMARY = PRIMARY prevSECONDARY = SECONDARY
Let's see how this code handles a series of entries, beginning with:
XView::18
The primary key doesn't match the previous primary key; the line is output as is:
XView::18
The next entry is:
XView:about:3
When we compare the primary key of this entry to the previous one, they are the same. When we compare secondary keys, they differ; we output the record as is:
XView:about:3
The next entry is:
XView:about:7
Because both the primary and secondary keys match the keys of the previous entry, we simply output the page number. (The printf function is used instead of print so that there is no automatic newline.) This page number is appended to the previous entry so that it looks like this:
XView:about:3,7
The next entry also matches both keys:
XView:about:10
Again, only the page number is output so that entry now looks like:
XView:about:3,7,10
In this way, three entries that differ only in page number are combined into a single entry.
The full script adds an additional test to see if the volume identifier matches. Here's the full pagenums.idx script:
#!/work/bin/nawk -f # ------------------------------------------------ # pagenums.idx -- collect pages for common entries # Author: Dale Dougherty # Version 1.1 7/10/90 # # input should be PRIMARY:SECONDARY:PAGE:VOLUME # ------------------------------------------------ BEGIN { FS = ":"; OFS = ""} # main routine -- apply to all input lines { # assign fields to variables PRIMARY = $1 SECONDARY = $2 PAGE = $3 VOLUME = $4 # check for a see also and collect it in array if (SECONDARY ~ /\([Ss]ee +[Aa]lso/) { # create tmp copy & remove "~zz" from copy tmpSecondary = SECONDARY sub(/~zz\([Ss]ee +[Aa]lso */, "", tmpSecondary) sub(/\) */, "", tmpSecondary) # remove secondary key along with "~zz" sub(/^.*~zz\([Ss]ee +[Aa]lso */, "", SECONDARY) sub(/\) */, "", SECONDARY) # assign to next element of seeAlsoList seeAlsoList[++eachSeeAlso] = SECONDARY "; " prevPrimary = PRIMARY # assign copy to previous secondary key prevSecondary = tmpSecondary next } # end test for see Also # Conditionals to compare keys of current record to previous # record. If Primary and Secondary keys are the same, only # the page number is printed. # test to see if each PRIMARY key matches previous key if (PRIMARY == prevPrimary) { # test to see if each SECONDARY key matches previous key if (SECONDARY == prevSecondary) # test to see if VOLUME matches; # print only VOLUME:PAGE if (VOLUME == prevVolume) printf (",%s", PAGE) else { printf ("; ") volpage(VOLUME, PAGE) } else{ # if array of See Alsos, output them now if (eachSeeAlso) outputSeeAlso(2) # print PRIMARY:SECONDARY:VOLUME:PAGE printf ("\n%s:%s:", PRIMARY, SECONDARY) volpage(VOLUME, PAGE) } } # end of test for PRIMARY == prev else { # PRIMARY != prev # if we have an array of See Alsos, output them now if (eachSeeAlso) outputSeeAlso(1) if (NR != 1) printf ("\n") if (NF == 1){ printf ("%s:", $0) } else { printf ("%s:%s:", PRIMARY, SECONDARY) volpage(VOLUME, PAGE) } } prevPrimary = PRIMARY prevSecondary = SECONDARY prevVolume = VOLUME } # end of main routine # at end, print newline END { # in case last entry has "see Also" if (eachSeeAlso) outputSeeAlso(1) printf("\n") } # outputSeeAlso function -- list elements of seeAlsoList function outputSeeAlso(LEVEL) { # LEVEL - indicates which key we need to output if (LEVEL == 1) printf ("\n%s:(See also ", prevPrimary) else { sub(/;.*$/, "", prevSecondary) printf ("\n%s:%s; (See also ", prevPrimary, prevSecondary) } sub(/; $/, ".):", seeAlsoList[eachSeeAlso]) for (i = 1; i <= eachSeeAlso; ++i) printf ("%s", seeAlsoList[i]) eachSeeAlso = 0 } # volpage function -- determine whether or not to print volume info # two args: volume & page function volpage(v, p) { # if VOLUME is empty then print PAGE only if ( v == "" ) printf ("%s", p) else # otherwise print VOLUME^PAGE printf ("%s^%s",v, p) }
Remember, first of all, that the input to the program is sorted by its keys. The page numbers are also in order, such that an entry for "graphics" on page 7 appears in the input before one on page 10. Similarly, entries for Volume I appear in the input before Volume II. Therefore, this program need do no sorting; it simply compares the keys and if they are the same, appends the page number to a list. In this way, the entries are reduced.
This script also handles "see also" entries. Since the records are now sorted, we can remove the special sorting sequence "~zz." We also handle the case where we might encounter consecutive "see also" entries. We don't want to output:
Toolkit (see also Xt) (See also XView) (See also Motif).
Instead we'd like to combine them into a list such that they appear as:
Toolkit (see also Xt; XView; Motif)
To do that, we create an array named seeAlsoList. From SECONDARY, we remove the parentheses, the secondary key if it exists and the "see also" and then assign it to an element of seeAlsoList. We make a copy of SECONDARY with the secondary key and assign it to prevSecondary for making comparisons to the next entry.
The function outputSeeAlso() is called to read all the elements of the array and print them. The function volpage() is also simple and determines whether or not we need to output a volume number. Both of these functions are called from more than one place in the code, so the main reason for defining them as functions is to reduce duplication.
Here's an example of what it produces for a single-book index:
X Window System:Xlib:6 XFontStruct structure::317 Xlib::6 Xlib:repainting canvas:88 Xlib.h header file::89,294 Xv_Font type::310 XView::18 XView:about:3,7,10 XView:as object-oriented system:17
Here's an example of what it produces for a master index:
reserved names:table of:I^43 Xt:example of programming interface:I^44,65 Xt:objects; list of:I^43,58; II^40 Xt:packages:I^43,61; II^42 Xt:programs; initialization:I^45 Xt:reserved names:I^43,58 Xt:reserved prefixes:I^43,58 Xt:types:I^43,54,61
The "^" is used as a temporary delimiter between the volume number and the list of page numbers.
The pagenums.idx program reduced entries that were the same except for the page number. Now we'll to process entries that share the same primary key. We also want to look for consecutive page numbers and combine them in ranges.
The combine.idx is quite similar to the pagenums.idx script, making another pass through the index, comparing entries with the same primary key. The following pseudocode abstracts this comparison. (To make this discussion easier, we will omit tertiary keys and show how to compare primary and secondary keys.) After the entries are processed by pagenums.idx, no two entries exist that share the same primary and secondary keys. Therefore, we don't have to compare secondary keys.
PRIMARY = $1 SECONDARY = $2 PAGE = $3 if (PRIMARY == prevPRIMARY) print :SECONDARY: else print PRIMARY:SECONDARY prevPRIMARY = PRIMARY prevSECONDARY = SECONDARY
If the primary keys match, we output only the secondary key. For instance, if there are three entries:
XView:18 XView:about:3, 7, 10 XView:as object-oriented system:17
they will be output as:
XView:18 :about:3, 7, 10 :as object-oriented system:17
We drop the primary key when it is the same. The actual code is a little more difficult because there are tertiary keys. We have to test primary and secondary keys to see if they are unique or the same, but we don't have to test tertiary keys. (We only need to know that they are there.)
You no doubt noticed that the above pseudocode does not output page numbers. The second role of this script is to examine page numbers and combine a list of consecutive numbers. The page numbers are a comma-separated list that can be loaded into an array, using the split() function.
To see if numbers are consecutive, we loop through the array comparing each element to 1 + the previous element.
eachpage[j-1]+1 == eachpage[j]
In other words, if adding 1 to the previous element produces the current element, then they are consecutive. The previous element becomes the first page number in the range and the current element becomes the last page in the range. This is done within a while loop until the conditional is not true, and the page numbers are not consecutive. Then we output the first page number and the last page number separated by a hyphen:
23-25
The actual code looks more complicated than this because it is called from a function that must recognize volume and page number pairs. It first has to split the volume from the list of page numbers and then it can call the function (rangeOfPages()) to process the list of numbers.
Here is the full listing of combine.idx:
#!/work/bin/nawk -f # ------------------------------------------------ # combine.idx -- merge keys with same PRIMARY key # and combine consecutive page numbers # Author: Dale Dougherty # Version 1.1 7/10/90 # # input should be PRIMARY:SECONDARY:PAGELIST # ------------------------------------------------ BEGIN { FS = ":"; OFS = ""} # main routine -- applies to all input lines # It compares the keys and merges the duplicates. { # assign first field PRIMARY=$1 # split second field, getting SEC and TERT keys. sizeOfArray = split($2, array, ";") SECONDARY = array[1] TERTIARY = array[2] # test that tertiary key exists if (sizeOfArray > 1) { # tertiary key exists isTertiary = 1 # two cases where ";" might turn up # check SEC key for list of "see also" if (SECONDARY ~ /\([sS]ee also/){ SECONDARY = $2 isTertiary = 0 } # check TERT key for "see also" if (TERTIARY ~ /\([sS]ee also/){ TERTIARY = substr($2, (index($2, ";") + 1)) } } else # tertiary key does not exist isTertiary = 0 # assign third field PAGELIST = $3 # Conditional to compare primary key of this entry to that # of previous entry. Then compare secondary keys. This # determines which non-duplicate keys to output. if (PRIMARY == prevPrimary) { if (isTertiary && SECONDARY == prevSecondary) printf (";\n::%s", TERTIARY) else if (isTertiary) printf ("\n:%s; %s", SECONDARY, TERTIARY) else printf ("\n:%s", SECONDARY) } else { if (NR != 1) printf ("\n") if ($2 != "") printf ("%s:%s", PRIMARY, $2) else printf ("%s", PRIMARY) prevPrimary = PRIMARY } prevSecondary = SECONDARY } # end of main procedure # routine for "See" entries (primary key only) NF == 1 { printf ("\n") } # routine for all other entries # It handles output of the page number. NF > 1 { if (PAGELIST) # calls function numrange() to look for # consecutive page numbers. printf (":%s", numrange(PAGELIST)) else if (! isTertiary || (TERTIARY && SECONDARY)) printf (":") } # end of NF > 1 # END procedure outputs newline END { printf ("\n") } # Supporting Functions # numrange -- read list of Volume^Page numbers, detach Volume # from Page for each Volume and call rangeOfPages # to combine consecutive page numbers in the list. # PAGE = volumes separated by semicolons; volume and page # separated by ^. function numrange(PAGE, listOfPages, sizeOfArray) { # Split up list by volume. sizeOfArray = split(PAGE, howManyVolumes,";") # Check to see if more than 1 volume. if (sizeOfArray > 1) { # if more than 1 volume, loop through list for (i = 1; i <= sizeOfArray; ++i) { # for each Volume^Page element, detach Volume # and call rangeOfPages function on Page to # separate page numbers and compare to find # consecutive numbers. if (split(howManyVolumes[i],volPage,"^") == 2) listOfPages = volPage[1] "^" rangeOfPages(volPage[2]) # collect output in listOfPages if (i == 1) result = listOfPages else result=result ";" listOfPages } # end for loop } else { # not more than 1 volume # check for single volume index with volume number # if so, detach volume number. # Both call rangeOfPages on the list of page numbers. if (split(PAGE,volPage,"^") == 2 ) # if Volume^Page, detach volume and then call rangeOfPages listOfPages = volPage[1] "^" rangeOfPages(volPage[2]) else # No volume number involved listOfPages = rangeOfPages(volPage[1]) result = listOfPages } # end of else return result # Volume^Page list } # End of numrange function # rangeOfPages -- read list of comma-separated page numbers, # load them into an array, and compare each one # to the next, looking for consecutive numbers. # PAGENUMBERS = comma-separated list of page numbers function rangeOfPages(PAGENUMBERS, pagesAll, sizeOfArray,pages, listOfPages, d, p, j) { # close-up space on troff-generated ranges gsub(/ - /, ",-", PAGENUMBERS) # split list up into eachpage array. sizeOfArray = split(PAGENUMBERS, eachpage, ",") # if more than 1 page number if (sizeOfArray > 1){ # for each page number, compare it to previous number + 1 p = 0 # flag indicates assignment to pagesAll # for loop starts at 2 for (j = 2; j-1 <= sizeOfArray; ++j) { # start by saving first page in sequence (firstpage) # and loop until we find last page (lastpage) firstpage = eachpage[j-1] d = 0 # flag indicates consecutive numbers found # loop while page numbers are consecutive while ((eachpage[j-1]+1) == eachpage[j] || eachpage[j] ~ /^-/) { # remove "-" from troff-generated range if (eachpage[j] ~ /^-/) { sub(/^-/, "", eachpage[j]) } lastpage = eachpage[j] # increment counters ++d ++j } # end of while loop # use values of firstpage and lastpage to make range. if (d >= 1) { # there is a range pages = firstpage "-" lastpage } else # no range; only read firstpage pages = firstpage # assign range to pagesAll if (p == 0) { pagesAll = pages p = 1 } else { pagesAll = pagesAll "," pages } }# end of for loop # assign pagesAll to listOfPages listOfPages = pagesAll } # end of sizeOfArray > 1 else # only one page listOfPages = PAGENUMBERS # add space following comma gsub(/,/, ", ", listOfPages) # return changed list of page numbers return listOfPages } # End of rangeOfPages function
This script consists of minimal BEGIN and END procedures. The main routine does the work of comparing primary and secondary keys. The first part of this routine assigns the fields to variables. The second field contains the secondary and tertiary keys and we use split() to separate them. Then we test that there is a tertiary key and set the flag isTertiary to either 1 or 0.
The next part of the main procedure contains the conditional expressions that look for identical keys. As we said in our discussion of the pseudocode for this part of the program, entries with wholly identical keys have already been removed by the pagenums.idx.
The conditionals in this procedure determine what keys to output based on whether or not each is unique. If the primary key is unique, it is output, along with the rest of the entry. If the primary key matches the previous key, we compare secondary keys. If the secondary key is unique, then it is output, along with the rest of the entry. If the primary key matches the previous primary key, and the secondary key matches the previous secondary key, then the tertiary key must be unique. Then we only output the tertiary key, leaving the primary and secondary keys blank.
The different forms are shown below:
| primary |
| primary:secondary |
| :secondary |
| :secondary:tertiary |
| ::tertiary |
| primary:secondary:tertiary |
The main procedure is followed by two additional routines. The first of them is executed only when NF equals one. It deals with the first of the forms on the list above. That is, there is no page number so we must output a newline to finish the entry.
The second procedure deals with all entries that have page numbers. This is the procedure where we call a function to take apart the list of page numbers and look for consecutive pages. It calls the numrange() function, whose main purpose is to deal with a multivolume index where a list of page numbers might look like:
I^35,55; II^200
This function calls split() using a semicolon delimiter to separate each volume. Then we call split() using a "^" delimiter to detach the volume number from the list of page numbers. Once we have the list of pages, we call a second function rangeOfPages() to look for consecutive numbers. On a single-book index, such as the sample shown in this chapter, the numrange() function really does nothing but call rangeOfPages(). We discussed the meat of the rangeOfPages() function earlier. The eachpage array is created and a while loop is used to go through the array comparing an element to the one previous. This function returns the list of pages.
Sample output from this program follows:
Xlib:6 :repainting canvas:88 Xlib.h header file:89, 294 Xv_Font type:310 XView:18 :about:3, 7, 10 :as object-oriented system:17 :compiling programs:41 :concept of windows differs from X:25 :data types; table of:20 :example of programming interface:44 :frames and subframes:26 :generic functions:21 :Generic Object:18, 24 :libraries:42 :notification:10, 35 :objects:23-24; :: table of:20; :: list of:43 :packages:18, 43 :programmer's model:17-23 :programming interface:41 :programs; initialization:45 :reserved names:43 :reserved prefixes:43 :structure of applications:41 :subwindows:28 :types:43 :window objects:25
In particular, notice the entry for "objects" under "XView." This is an example of a secondary key with multiple tertiary keys. It is also an example of an entry with a consecutive page range.
The previous scripts have done nearly all of the processing, leaving the list of entries in good order. The format.idx script, probably the easiest of the scripts, reads the list of entries and generates a report in two different formats, one for display on a terminal screen and one to send to troff for printing on a laser printer. Perhaps the only difficulty is that we output the entries grouped by each letter of the alphabet.
A command-line argument sets the variable FMT that determines which of the two output formats is to be used.
Here's the full listing for format.idx:
#!/work/bin/nawk -f # ------------------------------------------------ # format.idx -- prepare formatted index # Author: Dale Dougherty # Version 1.1 7/10/90 # # input should be PRIMARY:SECONDARY:PAGE:VOLUME # Args: FMT = 0 (default) format for screen # FMT = 1 output with troff macros # MACDIR = pathname of index troff macro file # ------------------------------------------------ BEGIN { FS = ":" upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" lower = "abcdefghijklmnopqrstuvwxyz" } # Output initial macros if troff FMT NR == 1 && FMT == 1 { if (MACDIR) printf (".so %s/indexmacs\n", MACDIR) else printf (".so indexmacs\n") printf (".Se \"\" \"Index\"\n") printf (".XC\n") } # end of NR == 1 # main routine - apply to all lines # determine which fields to output { # convert octal colon to "literal" colon # make sub for each field, not $0, so that fields are not parsed gsub(/\\72/, ":", $1) gsub(/\\72/, ":", $2) gsub(/\\72/, ":", $3) # assign field to variables PRIMARY = $1 SECONDARY = $2 TERTIARY = "" PAGE = $3 if (NF == 2) { SECONDARY = "" PAGE = $2 } # Look for empty fields to determine what to output if (! PRIMARY) { if (! SECONDARY) { TERTIARY = $3 PAGE = $4 if (FMT == 1) printf (".XF 3 \"%s", TERTIARY) else printf (" %s", TERTIARY) } else if (FMT == 1) printf (".XF 2 \"%s", SECONDARY) else printf (" %s", SECONDARY) } else { # if primary entry exists # extract first char of primary entry firstChar = substr($1, 1, 1) # see if it is in lower string. char = index(lower, firstChar) # char is an index to lower or upper letter if (char == 0) { # if char not found, see if it is upper char = index(upper, firstChar) if (char == 0) char = prevChar } # if new char, then start group for new letter of alphabet if (char != prevChar) { if (FMT == 1) printf(".XF A \"%s\"\n", substr(upper, char, 1)) else printf("\n\t\t%s\n", substr(upper, char, 1)) prevChar = char } # now output primary and secondary entry if (FMT == 1) if (SECONDARY) printf (".XF 1 \"%s\" \"%s", PRIMARY, SECONDARY) else printf (".XF 1 \"%s\" \"", PRIMARY) else if (SECONDARY) printf ("%s, %s", PRIMARY, SECONDARY) else printf ("%s", PRIMARY) } # if page number, call pageChg to replace "^" with ":" # for multi-volume page lists. if (PAGE) { if (FMT == 1) { # added to omit comma after bold entry if (! SECONDARY && ! TERTIARY) printf ("%s\"", pageChg(PAGE)) else printf (", %s\"", pageChg(PAGE)) } else printf (", %s", pageChg(PAGE)) } else if (FMT == 1) printf("\"") printf ("\n") } # End of main routine # Supporting function # pageChg -- convert "^" to ":" in list of volume^page # Arg: pagelist -- list of numbers function pageChg(pagelist) { gsub(/\^/, ":", pagelist) if (FMT == 1) { gsub(/[1-9]+\*/, "\\fB&\\P", pagelist) gsub(/\*/, "", pagelist) } return pagelist }# End of pageChg function
The BEGIN procedure defines the field separator and the strings upper and lower. The next procedure is one that outputs the name of the file that contains the troff index macro definitions. The name of the macro directory can be set from the command line as the second argument.
The main procedure begins by converting the "hidden" colon to a literal colon. Note that we apply the gsub() function to each field rather than the entire line because doing the latter would cause the line to be reevaluated and the current order of fields would be disturbed.
Next we assign the fields to variables and then test to see whether the field is empty. If the primary key is not defined, then we see if the secondary key is defined. If it is, we output it. If it is not, then we output a tertiary key. If the primary key is defined, then we extract its first character and then see if we find it in the lower string.
firstChar = substr($1, 1, 1) char = index(lower, firstChar)
The char variable holds the position of the letter in the string. If this number is greater than or equal to 1, then we also have an index into the upper string. We compare each entry and while char and prevChar are the same, the current letter of the alphabet is unchanged. Once they differ, first we check for the letter in the upper string. If char is a new letter, we output a centered string that identifies that letter of the alphabet.
Then we look at outputting the primary and secondary entries. Finally, the list of page numbers is output, after calling the pageChg() function to replace the "^" in volume-page references with a colon.
Sample screen output produced by format.idx is shown below:
X X Protocol, 6 X Window System, events, 84 extensibility, 9 interclient communications, 9 overview, 3 protocol, 6 role of window manager, 9 server and client relationship, 5 software hierarchy, 6 toolkits, 7 X Window ID for paint window, 87 Xlib, 6 XFontStruct structure, 317 Xlib, 6 repainting canvas, 88 Xlib.h header file, 89, 294 Xv_Font type, 310 XView, 18 about, 3, 7, 10 as object-oriented system, 17 compiling programs, 41 concept of windows differs from X, 25 data types; table of, 20 example of programming interface, 44 frames and subframes, 26 generic functions, 21 Generic Object, 18, 24
Sample troff output produced by format.idx is shown below:
.XF A "X" .XF 1 "X Protocol" "6" .XF 1 "X Window System" "events, 84" .XF 2 "extensibility, 9" .XF 2 "interclient communications, 9" .XF 2 "overview, 3" .XF 2 "protocol, 6" .XF 2 "role of window manager, 9" .XF 2 "server and client relationship, 5" .XF 2 "software hierarchy, 6" .XF 2 "toolkits, 7" .XF 2 "X Window ID for paint window, 87" .XF 2 "Xlib, 6" .XF 1 "XFontStruct structure" "317" .XF 1 "Xlib" "6" .XF 2 "repainting canvas, 88" .XF 1 "Xlib.h header file" "89, 294" .XF 1 "Xv_Font type" "310" .XF 1 "XView" "18" .XF 2 "about, 3, 7, 10" .XF 2 "as object-oriented system, 17"
This output must be formatted by troff to produce a printed version of the index. The index of this book was originally done using the masterindex program.
The masterindex shell script is the glue that holds all of these scripts together and invokes them with the proper options based on the user's command line. For instance, the user enters:
$masterindex -s -m volume1 volume2
to specify that a master index be created from the files volume1 and volume2 and that the output be sent to the screen.
The masterindex shell script is presented in Appendix C with the documentation.


Basics web pages
These web pages are to show all the different projects I can do.
E-commerce layout
Here you can find a e-comerce web page, with all the items and information about the products.
Pinterest-like page
Pinterest is a unique web page and this is my example for this kind of web page.


[button]
[button title='Single "quotes"' url="http://example.com"]
[button title="It's double quotes" url='http://example.com']
[button title=`It's literal quotes"` url=`http://example.com`]
[unset title="Non registered shortcode" content="It should not do anything"]


What does it mean to be human? How do we decide which path to take along the journey of our lives? On the streets of Velvet City, a wayward android scrounges for enough bitcoin to buy himself some code. Around the corner, an SCorp enforcer takes down a Terminal Tom for peddling illegal script. The city is full of stories.... this is yours.
You sit alone at your desk and count the minutes. Five minutes before you need to get on the beat. The office is half empty today.
As you lean back in your chair and start to count the ceiling tiles, your trapper keeper chimes a developing news alert.
Your stomach flapjacks. Fear slowly starts to creep in.
',' your trapper keeper chimes. It's Nia. 'I heard the news.  Pesky A.I."I'm ok, Nia, thank you. What's the global feed saying?" you ask.
'SCorp blames Planet Zeus' Nia replies.
The neural link, AKA "the brain potato," is arguably the most important innovation of the 21st century. No longer is nature the gatekeeper to untapped potential. The potato allows users to access, store, and recall any data type instantaneously. Rich, poor, young, old… everyone has one these days. Most get the implant directly after birth.
You can’t help but wonder… Will you be safe?
"Time to begin work !" the trapper keeper chimes as the clock read 8am.
“Same stuff… different day,” you mutter to yourself.  All you can think about is the event the Watchers are calling “The Crash.”You try to clear your mind of the news, opening applications and going through your daily routine to prepare for work.
Today you need to write an album review for the Screaming Valkyries latest, Null Dreams. There's the blog post, the copy, the images, an interview with Naoki Koda at 3, another piece a new jewlery app for Robo-Dogs. It's going to be a brutally busy day. Then you have a thought: maybe you should reach out to some contacts, see if you can learn more about the Crash?
Maybe Gabe would know something? He's a long-time friend, a chummer. He's also a bartender, so he might have some decent intel.
Or what about your old academy contact Zephyr?  She's never done you wrong though. Likes to talk conspiracy theories after a few sakes.
Maybe Gabe would know something? You've known him long time, he's a chummer. He's also a bartender, so he might have some decent intel.
Or what about your old academy contact Zephyr?  She's never done you wrong though. Likes to talk conspiracy theories after a few sakes.
5:00 p.m. Everyone usually clocks out at 4:45, but you prefer to do things by the book.4:45 p.m., technically clocking out on time, but not exactly aces on your quarterly. It seems like the world's going mad trying to figure out what happened.  Sort of a classy joint. They play music from long before the Reformatting.
Upon arriving, you notice the bar is nearly empty. What a mess of a day, half the newsroom empty too because of the Crash. Did they crash? Or someone they loved? You shudder. Gabe the bartender was there, polishing the glasses. When he sees you take a stool, he walks over and says, “Think maybe I got something for you, Newsy."
"Newsy. Ha! They never let me run my own leads." you scoff. A Newsy's only purpose is to write whatever SCorp tells them to. You find the term 'Newsy' repugnant. A fake word; a misnomer."Sure thing, Gabe." Newsy was the job title for anyone contracted by SCorp News to write for 'Tales from Velvet City,' a daily blog publication, and even if you had major doubts towards the authenticity of what you were writing, that was your job.
“Someone's been looking for you,” Gabe says as he walks a little closer. Bach's Prelude in C minor plays in the background.
“What can I say, I'm popular,” you say, taking a drink. Gabe reaches under the counter and produces a small storage unit with an ornate design. It has the text #: ENCRYPTED displayed on a mini LED screen.
“Strange looking one. All sorts of implants, black trench coat, mirrored eyes... He said that if I saw you, I should give you this. Seems a little sketchy, ." Gabe explained.
You reassure him, "All good, Gabe. Aces.” Gabe hands you the storage unit.
You open the unit and retreive a small phys drive. After pulling the contents, you see there is only one file, an audio file. The voice has heavy vocal distortion: "SCorp Bionetics, 10.4.99, Icarus commit #8991,". That's it. You scan around the bar to see if there's anyone watching you. Time to get home.
You finish your drink and settle up with Gabe. 'Hurdy Gurdy Man' is playing on the juke as you walk out the door into the polluted dusk.
You can’t stop thinking about the Crash, and feel like you need to know more. You go to Westwood Park to try to relax, but the old, dying trees and tainted sunlight give you no comfort. People mill by at a listless pace, gas masks over their faces.
Why did all those people crash? Is it going to happen again, or to you? You feel sick, uneasy, like you have to get to the bottom of this. One of your old chummers from academy might know. You heard she’d got a pretty nice gig with SCorp as an ICE controller. The park is now deserted, and seems sad, haunted. You stomp at a rat that scurries by your feet.
Ehh, it’s worth a shot.  You know anything about the Crash? I can’t shake it,” you say.
Zephyr stays silent for a few moments. “, don’t look too close. That’s my advice. Go to your job tomorrow, be merry, find a date this weekend.”
“Zeph, tell me. I need to know. What happened?”
She takes a moment to rub her brow. ENCRYPTED flashes onto the screen. “Fine, you asked for it. Look at SCorp's private repositories for Icarus.” The line disconnects...
Well... She looked really concerned. What could SCorp be hiding in their repos? It’s been a long day. Whatever Zeph pointed me towards, it’s probably not good. Time to get back home. As you walk, you see someone down and out slumped next to a tree.
 You're going to get to the bottom of this.
“Floor 4” the mag lift announces.
You step into the desolate hall of your apartment floor and make your way to door D2. The room is nearly empty save a bed, a nightstand, and a vintage Felix the Cat alarm clock from the early '90s. The techno greasy glow of the magenta city scape illuminates the cold room. You take a moment and finally decide that you need to know what is being hidden from the public about “The Crash.”
You set the brain potato to twice stuffed and frame jack into the SCorp repositories. You execute a bit of custom script and find something unusual. An error in the commit log for the latest neural link software update. There are several lines that are redacted. You dig deeper into the problem, only to discover the horrifying truth…
A bug. A nasty one. And even worse, SCorp knew it was going to happen, and they did nothing to stop it.
This could be the end of SCorp if anyone finds out…
"You have a new message, ," chimes your Trapper Keeper.
They call themselves Oshi… “You have the information I need. Help me change the world.”
Back at your at work the next day, you decide not to send the information. After all, you have no idea who this person is, or even if they can be trusted.
The mag lift dings open and a group of heavily armed SCorp enforcers step out.
You try to play it cool at first. Maybe they're not looking for you.
"FREEZE!" one of them shouts.
It seems as though you can't escape the wrath of SCorp. You make a mad dash and get to the stairwell at the opposite side of the room and hussle down 4 flights of stairs, then jump off the second floor balcony.
You don't look back. Running through the alleyways, you try to evade the omnipresence of dangerous, razor sharp wires that are devouring the cityscape.  And SCorp is hot on your tale.
You extricate yourself from the electric swine with your laser knife, then begin to run again. Just then a shadowy figure grabs your arm and yanks you in to a doorway.
"What the hell!... I didn't do anything," you say, readying your knife.
"Easy," the face says, from under a dark purple hood, "I'm a friend. You must follow me."
Seeing no other choice, you flee into the nefarious underground, away from the neon and harm, for now...
You create an encrypted data packet to send to your new contact. This wasn’t an easy choice, but the world deserves to know the truth. The moment the information is sent a security alarm screams into your ear, “Security channel compromised”.
“Oh shit” you whisper…
Any moment SCorp goons could break into your apartment, grab you, and lock you away never to be heard from again.
Trapper keeper in hand your make a mad dash for the door. As you step into the hallway you see a large shadowy figure at the end.
SCorp works quick. You make a mad dash for the mag lift and hit the button for the basement. The shadowy figure sprints to the lift door as it close inches before his face.
As the lift races to the basement you start to panic… Where can you go? Who can you trust? You send your journalist contact a message “Help, SCorp is on my tail”
“Ditch the heat and meet me in The Velvet Underground. Block E, 5th avenue access hatch. Pass code is xeon”
In the early 21st century Velvet City was a major port located on a bustling waterway. By 2099 the river had been diverted to serve other SCorp interests. The dried up canals became The Velvet Underground. A haven for people looking to get lost.
You arrive at Block E, 5th avenue access hatch and key in the code “xeon”.
You step into the small dimly lit room. In the corner, a man in a purple hoodie is leaning against the wall. He takes down his hood.
“Hello, . My name is Oshi. I'm with an organization called the Watchers. We need to talk,” the journalist says to you.
“Then talk,” you reply.
"Not sure how you got that intel, but now you know, it was all SCorp. They pushed a blank master copy on millions of people, and now they won't own up to their mistake. And it seems you have the proof."
Could it be that horribly simple?
People need to know, but you fear that the panic incited could cause global pandemonium. While the journalist seems intent on setting the world ablaze… you still have pause. Maybe it was a one time mistake? Will you help the journalist expose the truth?
Or maybe it’s not too late to make nice with SCorp.
Something perturbs you. You realize you have seen this journalist before. It seems as if you crossed paths at a local seafood restaurant. He was in a bathroom stall and abruptly left with a viscous terrier under his arm while you were washing your hands.  You need to turn him in.
The Journalist's lack of hygiene offended you immensely. But what happened after that was much worse.  The act flayed all your senses. So you made the decision to turn him in.
Several android enforcers enter the bar and take seats all around you. You order a drink for the one sitting next to you, saying nothing.
"You did the right thing," they say.
"I figure the evil I know is better than the one I don't," you say.
 You turn on your favorite reality TV show, "Climbing for Dollars."
It doesn't give you much satisfaction. You snap off the TV, climb in to bed, and think about the madness you discovered today.
A few days later you awake at the Watchers pad to the sound of helicopters overhead. This is bad. Really bad. SCorp is on to you. They must have found out it was the Watchers that leaked the info. You check the Watcher newsfeed.
It’s fight or flight time.
Finally you get it started, and take off at speed. Your heart is pounding. Is it the end?
All of the sudden, two black SUVs pull up and block the intersection. Panic races through your body. You turn the bike around and attempt to go the other way, but 4 other SUVs pull up to block the opposite side of the street. The jig is up. You’re geeked.
 Androids in black suits begin piling out of the vehicles. How do so many fit inside?
“People deserve to know!” you shout, “We’re awake now!”
They form up, surrounding you. There must be 100… They stand alert, silent.
Was it worth it? This is what humanity needed to expose SCorp, you tell yourself.  For what? The potatoes made life better, but now...
Whatever happens to you, you feel like the world is entering a strange, new age, and that you and the other Watchers were the ushers to this great transformation.


Some info here
If nothing happens after about a minute or two, please refresh the page and try again.


This is a compilation of questions from the main Dusk forum post and elsewhere, as well as other helpful questions to help you use Dusk.
bodyType
to my physics objects? physics:bodyType
doesn't work!map.layer
/layer.object
table?map:removeSelf()
, all sorts of nasty errors appear.You can add physics to tiles or objects in one of two ways.
Through tile or object properties. To do this, edit the properties of a tile in a tileset or an object in a layer, and add the property physics:enabled
as true
. Then, you can add other physics options by prefixing them with physics:
. Everything prefixed with physics:
is automatically added to the physics table when an object or tile is created. For example, to add the bounce
or friction
properties, use physics:bounce
and physics:friction
.
Through layer properties. If you set up physics through layer properties (viz. add a physics:enabled
property and options to the layer instead of to the layer's children), physics will be passed to the layer's children automatically, because layers aren't physics-enabled. Thus, any physics options you add to a layer will be added to the layer's children instead. Everything detailed in the paragraph above applies here.
An important thing to note is that two physics properties behave differently. The isSensor
property can be added to the physics table (that is, physics:isSensor
), but it can also be added directly to the object as a property. The bodyType
property can only be added to the object as a property, and does not go inside the physics table. If you specify physics:bodyType
in your options, nothing will appear to happen. You will have to set it as a simple property, without the physics:
prefix. You can make the property apply to all children of a layer by prefixing the option with tiles:
or objects:
for tile layers and object layers, respectively.
One of the things that makes Dusk a good engine is its tile culling capabilities. Tile culling is the removal and addition of tiles as needed as the map moves around the screen. By using tile culling, tile engines like Dusk are able to load maps of a far bigger size (25,000,000 - twenty-five million - is the most I've ever tried), because the only tiles that really exist are the ones currently visible in the screen.
Your problem is likely that you're forgetting to call map.updateView()
as you move your map around. Simply place this function call in an enterFrame
listener in your code, and add a call to it when you move the map, and this problem will be solved.
This is a simple fix. Make sure everything you want to move with the camera is inserted into one of the map's layers.
bodyType
to my physics objects? physics:bodyType
doesn't work!As detailed in How do I add physics to tiles or objects?, the bodyType
property is different in Corona from the rest of the physics properties. It requires that you add it as a plain property instead of in the physics table. Thus, for an object or tile, bodyType
will work; for a layer's children, objects:bodyType
or tiles:bodyType
will work.
Use the layer._lockTileErased(x, y)
function. This function erases the tile if it exists and keeps it from being drawn in the future. You can then unlock it with layer._unlockTile(x, y)
. The inverse of this is layer._lockTileDrawn(x, y)
, which forces the tile to stay drawn even when it goes outside the screen's bounds.
First, add the following two lines to the top of your main.lua
:
display.setDefault("minTextureFilter", "nearest")
display.setDefault("magTextureFilter", "nearest")
Then, make sure your tileset has a spacing of at least 1 pixel. Spacing is the distance between tiles in a tileset. Dusk ought to fix everything else automatically.
For a slightly more effective approach to getting rid of this, you can extrude your tilesets by 1 or 2 pixels.
map.layer
/layer.object
table?Dusk stores each layer two times: once under map.layer[index]
and once under map.layer[name]
. This is so that you can access each layer either through the layer's index or the layer's name. For iterating through each layer, you should use one of the designated layer iterators.
The same thing applies to layer.object
. Each object gets two references as well.
map:removeSelf()
, all sorts of nasty errors appear.The correct way to remove a map is via the map.destroy()
function.
Use the map.setCameraFocus(player)
function. It will tell Dusk to stay focused on an object. Don't forget to call map.updateView()
every frame, or the camera will appear to do nothing.
Use the map.setTrackingLevel(t)
function. It takes a number from 0 to 1, and makes the camera more or less "fluid" and slow to track. Numbers approaching 0 are more fluid. A tracking value of 0.3 or 0.4 is usually good for most games.
Alternatively, you can use the map.setDamping(d)
function; it takes any number over zero and sets the tracking level inversely. For this, higher numbers make the camera slower.
This is a common drawback of using a real physics engine for a tile-based game. There are several ways to get around this:


ClimateScape is a kinetic art installation using sound and movement.
Climate change is happening. Some think we've already gone too far.
We need to make a concentrated effort to about face immediately. A dramatic shift on current climate policy and swift action is no longer an option, it is mandatory. The time is now and it may be running out, if it hasn't already.
ClimateScape is about bringing awareness to the human effect and how we are affecting climate change. The four soundscape sculptures represent 4 potential climate change scenarios known as Representative Concentration Pathways, or RCPs.
They are scenario models for forecasters to use when modeling certain climate related metrics.
As the sculptures are approached they engage with the viewer and create a sometimes uneasy soundscape representing one of these scenarios. Illustrating the human effect and how we are influencing these changes.
The sculptures also have a representative material, representing a current and / or future sector that is or will be playing a role in climate change.
We are the human effect and we cause the ClimateScape.
It is up to us to right the ship. We as artists must bring continued awareness. We as humans must act.
The RCP’s are representative greenhouse gas trajectories adopted by the Intergovernmental Panel on Climate Change(IPCC) in 2014. It basically describes best and worst case scenerios if we (humans) take action on climate change or do nothing.
These pathways can then be used to map out projections on potential global warming and sea level rise as well as other metrics we may see over the next 100 years.
The RCP 2.6 scenario can be seen as the best case senario. We need to make a stark turnaround on current climate change polices and begin a combined global effort to take action soon. Some say the window is closing quickly if it has not already.
This scenario forecasts global emmisions to peak by 2020 and to decline to zero towards the end of the century.
The RCP 2.6 soundscape represents the best case scenario with a representative material of grass. Grass can be made into bio-fuel or bio-energy, which in the year 2100 is forecasted to make up 29% of our energy resource.
Emissions peak 50% higher than 2000 levels by mid century and decrease quickly over the next 30 years. The climate stabilizes at about half of 2000 levels around 2070.
Representative Sector: Industry. Industry is the 3rd largest contributor to emissions currently.
Representative Material: onetime use plastics.
RCP 6 projects emissions have doubled by 2060. Then they drop quickly but stay much much higher than current levels.
C02 concentration still increases, slows the later part of the century.
Representative Sector: Electricity. Electircity is the 2rd largest contributor to emissions currently.
Representative Material: coal.
Is the worst case scenario. Emmissions continue to increase rapidly through the early to mid century.
By 2100 annual emmissions have stablized but increasd almost 74%.
Population growth is high and environmental and sustainable resource levels are low. Oil use grows swiftly until 2070 and then begins to drop. Coal is the bulk of the increase energy consumption. Land use continues current trends.
Representative Sector: Transportation. Transportation is the largest contributor to emissions currently.
Representative Material: tire/rubber.


This show some examples about setting up a grid of static width.
This column has a width of 1 grid unit.
This column has a width of 2 grid units.
This column has a width of 1 grid unit.
This column has a width of 3 grid units.
This column has a width of 1 grid unit.
This column has a width of 4 grid units.
This inner column has a width of 1 grid unit.
This inner column has a width of 2 grid units.
This column is 6 grid units wide in the main grid, like the one on the left side.
On the left: There is an inner column set inside the column, with a total of 3 columns.


This command allows any script in any session to add title bar and the thick borders to any session window.
Example:
/autoexec {/window {helpview.mms}{/addcaption}}
Click here to return to previous page.


Profile Settings
Social Connections
{{alert.msg}}
Disconnect {{property.text}}
Connect {{property.text}}
{{ data }}
{{key}}
Set Your Avatar
Drop Image Here
{{files[0].name}}
Set Photo
Set Password
{{alert.msg}}
New Password:
This field is required
Confirm Password:
This field is required
Set Password
Identity
{{alert.msg}}
Username:
{{ user.username }}
Email:
{{ user.email }}
FirstName
This field is required
Please enter a valid firstName
{{errfor.firstName}}
LastName:
This field is required
Please enter a valid lastName
{{errfor.lastName}}
Property Address:*
This field is required
City:*
This field is required
State:
Zip:*
5 Digit Only
Phone:*
This field is required
Your Markets:
Atlantic
Hunterdon
Sussex
Gloucester
Salem
Cumberland
Ocean
Camden
Monmouth
Bergen
Merser
Union
Hudson
Somerset
Essex
Passaic
Cape May
Morris
Burlington
Middlesex
Warren
How did you hear about us?:
This field is required
I'd like to receive additional information from www.NJBirdDogs.com about real estate and property locating opportunities
Update


Discovery research
Who the users are and what they need
Ultimately we know everyone’s affected by cybercrime.
To begin to test and broaden our assumptions about what people need, we held one-on-one conversations with potential and actual victims of cybercrime and collected stories from people who’ve witnessed and fallen victim to cybercrime through a story gathering tool.
We learned that most victims don’t identify themselves as victims of “cybercrime”. They might use more specific terms like “identity theft” or might be most comfortable describing their experience. They do not use the same categories to describe a cybercrime event that law enforcement use.
Early on, we learned that the public needs:
- Low-burden reporting
- Nudges to report
- Mitigation advice
- Emotional reassurance
- Evidence sharing
Why people report cybercrime
Altruism
Altruists want to report crime to help prevent it from happening to others. They are trying to protect others by helping the authorities. They report because “it’s the right thing to do”.
Problem solving
Solvers try to fix the problems the crime poses for them or their friends and family. They want to recover money, clean computers, stop anything else bad from happening. They report to police, but only if they believe the police can help them mitigate the damage of the crime.
Justice seeking
Justice seekers want the criminals caught; they look for “hands in cuffs”. They might want their money recovered, but they really want justice done. They collect and submit evidence about the crime and are sometimes disappointed when no investigation proceeds.
Why people don’t report cybercrime
Feeling embarrassed, ashamed, at fault
If a victim feels like they did something wrong, they will not share crucial details about their experience. They also may not report when they are not aware that what they experienced warrants finding help.
Not knowing what the options are for reporting
Because victims don’t know what a cybercrime is (in legal terms), they don’t know who to turn to for help, and are often unable to find help to begin with. They don’t report when they are overwhelmed by an ambiguous process.
Being disappointed or intimidated by law enforcement
When victims complete a report, they expect follow-up and respect from the police. If police are not responsive, victims avoid going to them for help when another incident occurs.


Then I deleted it before posting, because when you argue about English usage, no-one wins.
Now, I feel smug for being correct, and smug for doing the right thing. Smuggy, smuglish smugness. How pleasant to start ones weekend with an entirely unjustified sense of superiority and also eggs! Perhaps with those little soldiers and some salt. Hmm, yes.
My attention begins to flag, dear reader. Until next time.


*** out of ****
Year: 1999 Starring Tom Hanks, David Morse, Bonnie Hunt, Michael Clarke Duncan, James Cromwell, Michael Jeter, Graham Greene, Doug Hutchison, Sam Rockwell, Barry Pepper, Patricia Clarkson, Harry Dean Stanton Screenplay by Frank Darabont Directed by Frank Darabont Rated R
What is it about Frank Darabont and prison films based on Stephen King novels? His "Shawshank Redemption," based on a King novella and taking place in a prison setting, collected several Oscar nominations in 1994 (including Best Picture), and has since become a major fan-favorite, constantly ranking high on Internet movie polls. "The Green Mile," also set in a prison and based on a series of books written by King, is Darabont's latest effort. Just in time for the Christmas season, the writer-director delivers what audiences are often looking for at this time of year: a weepy drama that packs an emotional punch and preaches a humanist message. "The Green Mile," though by no means a perfect film, succeeds on both levels.
Two-time Oscar winner Tom Hanks stars as Paul Edgecomb, a prison guard in charge of death row, otherwise known as "the green mile" because of its linoleum-tile floor. A new prisoner catches his eye: John Coffey (Michael Clarke Duncan), a massive black man convicted of raping and murdering two young girls. To Edgecomb and the other guards (David Morse, Barry Pepper, Jeffrey DeMunn), Coffey seems exactly the opposite from his profile. Though large, he is a gentle giant who loves animals and is afraid of the dark. Edgecomb suspects Coffey may have been unjustly convicted, and his suspicions are raised even more when the prisoner begins exhibiting a strange supernatural power: the power to heal people. Other characters in this colorful group include Percy Wetmore (Doug Hutchison), a stuck-up sadistic guard who only has his job because he's related to the governor, and the other prisoners, which include Arlen Bitterbuck (Graham Greene), a quiet Native American; "Wild" Bill Wharton (Sam Rockwell), an insane serial killer; and Eduard Delacroix (Michael Jeter), a Cajun who takes a mouse living in the block for a pet. The mouse, called Mr. Jingles, provides a source of amusement for the guards and inmates, save for Percy, who has been frustrated in his attempts to catch the mouse.
The strong suit of "The Green Mile" is the acting. Tom Hanks, excellent as usual, takes another step towards his evident goal of becoming this generation's Jimmy Stewart, with a sympathetic, human performance. He's surrounded by a fine supporting cast, most notably Michael Duncan as John Coffey and David Morse as Edgecomb's right-hand man "Brutal" Howell. Each would be a fine choice for a Supporting Actor nomination. The characters remain somewhat sketchy, this being a narrative-oriented fable, but Duncan and Morse manage to find some underlying humanity underneath what the script gives them. The story also contains villains, with Doug Hutchison having a great deal of fun as Percy, the world's biggest cad, and Sam Rockwell hamming it up as the psychotic Wild Bill. Do they resemble real people? No, but they still serve their purpose: to give the audience someone to root against. In Percy's case, this shouldn't be a problem. Some well-known actors show up in relatively small roles, such as James Cromwell (whose part probably should have been larger) as Warden Hal Moores, Gary Sinise in exactly one scene (a good one) as Coffey's lawyer, and Bonnie Hunt as Edgecomb's supportive wife Jan. This film is lifted by all-around good performances, one of the finest casts that could have been assembled.
Darabont's direction seems to exist in sharp contrast to the modern quick-cut, moving-camera style so common to young directors. He engages in elegant, throwback storytelling, in which he holds back most of the time and pulls out all the stops for the big emotional climaxes, of which "The Green Mile" has many, most resulting from Coffey's supernatural gifts. Darabont swells the music, utilizes close-ups of his actors' faces, and plays the audience's emotions like a drum. Of course, it's not as though the audience will complain much about this sort of thing, being that it's what we expect at this time of year. "The Green Mile" is a melodrama, a bit hokey, but still effective. The film is lengthy, at over three hours of running time, but strangely refuses to drag. It moves fairly quickly, leaving me hard-pressed to come up with a way Darabont could have edited it without damaging the narrative, save for one: the elderly bookends, in which an aged Paul Edgecomb narrates the script's main story, are fairly unnecessary, with the closing one providing not only a major anticlimax, but a seeming contradiction to the film's original message. It's a similar problem to those that marred two other highly-touted "epic" films of the past two years, "Titanic" and "Saving Private Ryan." I'm still unclear as to why filmmakers feel the need to include these devices. They don't add much to the story, and merely cause the audience to leave on a bit of a let-down, dragging on after the primary narrative has already run its course.
Other than the unnecessary bookends, the only other thing "The Green Mile" suffers from is being overly familiar. If you've ever read a fairy tale, you 'll know exactly what's going to happen when credits roll. The good guys will come out on top, and the bad guys will get their just desserts. Furthermore, the script contains several plot contrivances that, while not major atrocities, do tend to get bothersome after a while. Case in point: when the real identity of a particular inmate is revealed near the end of the film, it seems a little too coincidental to believe. Contrivances aside, this film doesn't claim to be an exact representation of real life. (How could it be, with so many non-racist white guards and a major supernatural element?) It's a fable, and an effective one. The emotional climaxes hit like a ton of bricks, and I must admit that I even got choked up a few times.
"The Green Mile" is certainly not a perfect film, and probably not the major Oscar contender the filmmakers intended it to be, but it is a well-acted, tautly-directed film with emotional weight. It's schmaltzier elements (like the affectionately cute Mr. Jingles) actually seem in place. You won't receive any great revelations about the human condition from this movie, and it's not remotely realistic, but with so many things going for it, it's not hard to overlook such flaws and see the film for what it is: a story very well told.
-reviewed by Shay Casey
For more reviews, go to http://www.geocities.com/Hollywood/Land/4252/movies.html
The review above was posted to the
rec.arts.movies.reviews newsgroup (de.rec.film.kritiken for German reviews).
The Internet Movie Database accepts no responsibility for the contents of the
review and has no editorial control. Unless stated otherwise, the copyright
belongs to the author.
Please direct comments/criticisms of the review to relevant newsgroups.
Broken URLs inthe reviews are the responsibility of the author.
The formatting of the review is likely to differ from the original due
to ASCII to HTML conversion.
Related links: index of all rec.arts.movies.reviews reviews


{% extends "base.html" %} {% block content %}
Upload an essay for analysis (.docx, .txt, .odt, .doc, .pdf, .rtf).
--Erich Fromm
Open Prose Metrics provides powerful insights for ELA and composition students, writing coaches, ELA teachers, and special education teachers.
The platform intends to support users looking for data-driven insights about writing while avoiding prescriptivist imperatives. Tasks for which users rely on this tool are broad:
OPM has been developed based on the creators' 35 years of combined experience working with secondary and post secondary students in the areas of composition, rhetoric, argumentation, research, and writing from sources. We have served as special and general educators for students with a variety of learning preferences.
Because of that foundation, the tool focuses on such diverse issues as concision and precision and basic sentence structure.
The following exemplify the scope of written expression, written mechanics, and rhetorical concerns the tools can address:
OPM is a tool to support substantive revision. It is data driven: making every effort not to be prescriptive, ExtraEyes is focused on providing data that can offer insight that drives substantive revision. In almost any case, prescriptivist suggestions are available in other tools.
Writing may be submitted via file upload, via paste, and by URL.
The most reliable way to analyze a file is to upload a document in .docx format.
Other acceptable formats include: .doc, .odt, .txt, .rtf.
In paste mode, the user can paste plaintext into a field and submit it for analsis. This is a reliable way to submit.
URL scraping is not a reliable feature yet. It works great on some pages, but either rejects or mungs other pages
Data to support revision using Lanham's Paramedic Method. To learn more about Lanham and the Paramedic Revision Method, explore the links below:
Get vital statistics about your document to reveal patterns and practices, and use them to make well-deliberated revisions.
Readabily scores/indexes are usually used to help us write down for our audiences in an effort to reduce confusion.
However, each index, looked at with the text statistics, can offer us powerful insights regarding writing; they may reveal breadth and depth of relevant content-area vocabulary, a strong ability to mix sentence types, or opportunities to improve sentence variety, for example.
The anaylsis of the submitted text includes style suggestions to be considered (or disregarded).
Track student progress on final revisions over time


source
code documentation
- Global ipsec_ah_check (ipsec_ip_header *outer_packet, int *payload_offset, int *payload_size, sad_entry *sa)
- Extend function to support transport mode
- Global ipsec_ah_encapsulate (ipsec_ip_header *inner_packet, int *payload_offset, int *payload_size, sad_entry *sa, __u32 src, __u32 dst)
- Extend function to support transport mode
- Global ipsec_ah_encapsulate (ipsec_ip_header *inner_packet, int *payload_offset, int *payload_size, sad_entry *sa, __u32 src, __u32 dst)
- fix TTL update and checksum calculation
id must be generated properly and incremented
- Global DUMPDEV_IGNORE_RESPONSE
- this feature is not implemented
- Global dumpdev_input (struct netif *netif)
- simulate reception of new packets HERE
replace this loop with memcpy()
ATTENTION: should be real IP, not -1
- Global ipsec_esp_encapsulate (ipsec_ip_header *packet, int *offset, int *len, sad_entry *sa, __u32 src_addr, __u32 dest_addr)
- fix TTL update and checksum calculation
id must be generated properly and incremented
- Global ipsec_output (unsigned char *packet, int packet_size, int *payload_offset, int *payload_size, __u32 src, __u32 dst, spd_entry *spd)
- invoke IKE to generate a proper SA for this SPD entry
- Global ipsecdev_init (struct netif *netif)
- this should be somewhere else
selecting the right interface for mapping must be replaced by an more generic method
MAC addresses should be set somewhere else
- Global ipsecdev_input (struct pbuf *p, struct netif *inp)
- Attention: the pbuf structure should be updated using pbuf_header()
- Global ipsecdev_output (struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr)
- this static access to the HW device must be replaced by a more flexible method
lwIP TCP ESP outbound processing needs to add data after the original packet. Since the lwIP TCP does leave any room after the original packet, we copy the packet into a larger buffer. This step can be avoided if enough room is left after the packet when TCP allocates memory.
- Global ipsec_sad_add (sad_entry *entry, sad_table *table)
- right now there is no special order implemented, maybe this is needed
- Global ipsec_sad_add (sad_entry *entry, sad_table *table)
- this part needs to be rewritten when an order is introduced
- Global ipsec_sad_del (sad_entry *entry, sad_table *table)
- right now there is no special order implemented, maybe this is needed
- Global ipsec_sad_get_free (sad_table *table)
- this function should probably be static
- Global ipsec_spd_add (__u32 src, __u32 src_net, __u32 dst, __u32 dst_net, __u8 proto, __u16 src_port, __u16 dst_port, __u8 policy, spd_table *table)
- right now there is no special order implemented, maybe this is needed
- Global ipsec_spd_add (__u32 src, __u32 src_net, __u32 dst, __u32 dst_net, __u8 proto, __u16 src_port, __u16 dst_port, __u8 policy, spd_table *table)
- this part needs to be rewritten when an order is introduced
- Global ipsec_spd_del (spd_entry *entry, spd_table *table)
- right now there is no special order implemented, maybe this is needed
- Global ipsec_spd_del (spd_entry *entry, spd_table *table)
- probably the SA should also be deleted
- Global ipsec_spd_get_free (spd_table *table)
- this function should probably be static
- Global ipsec_spd_lookup (ipsec_ip_header *header, spd_table *table)
- port checking should be implemnted also
- Global IPSEC_TESTING_EVALUATE (__retcode__, __sub_results__, __functionname__, __msg__)
- this doxygen tag is not working. probably because of the complexity of the macro
|


Show:
Blacklist
Whitelist
Graylist
Export:
Blacklist
Whitelist
Graylist
Auth Key:
List:
Blacklist
Whitelist
Graylist
Action:
Add
Remove
Reset
Names:
Submit


[gecode-users] IntSet question
Guido Tack
tack at gecode.org
Mon Aug 2 17:31:46 CEST 2010
Gustavo Gutierrez wrote:
> Probably what I am going to ask is not useful or is just to much particular to my case that does not worth have it, however, I wouldn't hesitate to ask :).
>
> While writing a propagator I realized that keeping some state in it will lower the complexity. This propagator is on a finite set variable and what I does is to track "the new elements in the glb" and propagate according with its semantics. At the beginning to I was using an std::set to keep the "old values" and using it to compute the new elements:
>
> new elements = current glb \ old values
>
> The propagator was performing well but the memory consumption and the time to compute the intersection was quite high. After realizing that I start using an IntSet instead of a std::set to keep the data. The advantage is that the IntSet stores ranges and then is *hopefully* less memory hungry. There is also something nice, you can use all the iterators with them (range iterators). The only problem is that they are intended to be used only to represent variable domains in initializations or when posting constraints and this is reflected in the fact that they lack of "modification operations" in the API.
>
> In my case I have to copy construct all the time and this is of course time consuming but far better than my previous implementation. Now my question, sounds it very crazy or stupid to use the IntSet in this way?, if it does not, then it would be nice to provide an specialization (via inheritance, for instance) that allows this kind of use. What do you think?
Yes, that is very crazy :-) However, there's a different data structure you can use in exactly the way you describe. It's actually two data structures, LUBndSet and GLBndSet. The difference is in the available operations: LUBndSet has intersectI and excludeI operations (i.e., it can shrink), and GLBndSet has an includeI operation (i.e., it can grow). These sets are used internally for implementing set variables. In your case, you'd use a GLBndSet (and includeI the current lower bound after each propagation). There's an iterator called BndSetRanges that you can use on these sets.
You should have a look at the IntersectionN propagator, it uses a LUBndSet to remember the intersection of all assigned variables it has seen so far (it will show you how to initialize and copy these sets).
Cheers,
Guido
--
Guido Tack, http://people.cs.kuleuven.be/~guido.tack/
More information about the users
mailing list


| Nome | Apelido | Valor do Contrato | Data Nascimento | Telefone | Genero | ||
|---|---|---|---|---|---|---|---|
| Nome | Apelido | Valor do Contrato | Data Nascimento | Telefone | Genero | ||
| Tiger | Nixon | System Architect | Edinburgh | 61 | 2011/04/25 |<EMAIL_ADDRESS>| favorite dvr close |
| Tiger | Nixon | System Architect | Edinburgh | 61 | 2011/04/25 |<EMAIL_ADDRESS>| favorite dvr close |
| Tiger | Nixon | System Architect | Edinburgh | 61 | 2011/04/25 |<EMAIL_ADDRESS>| favorite dvr close |
| Tiger | Nixon | System Architect | Edinburgh | 61 | 2011/04/25 |<EMAIL_ADDRESS>| favorite dvr close |
| Tiger | Nixon | System Architect | Edinburgh | 61 | 2011/04/25 |<EMAIL_ADDRESS>| favorite dvr close |
| Tiger | Nixon | System Architect | Edinburgh | 61 | 2011/04/25 |<EMAIL_ADDRESS>| favorite dvr close |
| Tiger | Nixon | System Architect | Edinburgh | 61 | 2011/04/25 |<EMAIL_ADDRESS>| favorite dvr close |
| Tiger | Nixon | System Architect | Edinburgh | 61 | 2011/04/25 |<EMAIL_ADDRESS>| favorite dvr close |
| Tiger | Nixon | System Architect | Edinburgh | 61 | 2011/04/25 |<EMAIL_ADDRESS>| favorite dvr close |
| Tiger | Nixon | System Architect | Edinburgh | 61 | 2011/04/25 |<EMAIL_ADDRESS>| favorite dvr close |
| Tiger | Nixon | System Architect | Edinburgh | 61 | 2011/04/25 |<EMAIL_ADDRESS>| favorite dvr close |
| Tiger | Nixon | System Architect | Edinburgh | 61 | 2011/04/25 |<EMAIL_ADDRESS>| favorite dvr close |
| Tiger | Nixon | System Architect | Edinburgh | 61 | 2011/04/25 |<EMAIL_ADDRESS>| favorite dvr close |


On Wednesday at the Lighthouse we (the Lighthouse team + the Happenstance residents & organisers) held an Open House event, talking to our guests about some of the work me and James have done on the project so far and what Happenstance is all about.
Happenstance brings together technologists and arts organisations to infuse the latter with the technological understanding and innovative approaches of the former. Putting people together in the same room is a remarkably simple yet underrated idea. Running the experiment three times in three different organisations hopefully will show which parts of it can be replicated and which were just a fluke.
After the Lighthouse team have been using a tool for recording team processes me and James have built – Offbott – for a while, I suggested doing daily stand-up meetings and banning email for internal communications, in the spirit of the Agile manifesto. It’s been interesting for me to find out this way exactly how everyone works and what their work involves, though of course I had hoped this would also prove equally interesting to everyone else.
Not everyone always works on the same projects together, and knowing what everyone else does and how they do it is useful. I would like to think I’ve contributed to the understanding the value of inspecting your processes and seeking ways to improve them through reflection and discussion.
The second (and last!) Open House even will be held on Tuesday 19 June at Lighthouse. Do come along to hear more.


-
CTRL+u clears from cursor to beginning of line
-
CTRL+k clears from cursor to end of line
-
CTRL+d clears one character to the right of the cursor
-
Esc+Backspace clears one word to the left of the cursor
-
Esc+d clears one word to the right of the cursor
-
Alt+left/right jumps to the beginning of the previous/next word
-
Ctr+a jumps to start of line
-
Ctr+e jumps to end of line
To clear the entire screen add the following alias to your ~/.bashrc
file:
alias cls="echo -ne '\033c'"
Now, in a new terminal typing cls
will clear everything including the scroll buffer. It
works much faster than reset
since it does not reset anything.
In fact reset
is only needed when you want to fix a broken terminal, e.g. after running
cat
on a binary file.
If you are on OSX, then Command (⌘)+k will clear the terminal (also works in the chrome devtools console).


04/25/14 Staying positive
Looking back at the identified values in my blog post About Values I think that especially 'Control', 'Credability', 'Inner Harmony' and 'Recognition' can be impacted in a stereotyped environment. In another blog post called About Stereotypes, I linked being stereotyped to the feeling of 'being watched and mistunderstood'. There is certainly a direct connection between these feelings and the level of how I see important values being respected. Threats like stereotypes impact my inner harmony and that in turn impacts my mood, behaviour/ productivity and how affirmated I feel.
On the other hand, valueing 'Responsibility', 'Courage' and 'Helping others' will hopefully help me see and mediate stereotype threat.
I strongly believe that DBC creates an open environment and encourages students to talk. This includes pair programming, exchanging ideas as well as sharing feelings like we do in our cultural blog posts.  But what I've experienced so far is that our group is not a group of solo ignorant fighters but everybody is appreciating giving and receiving feedback and helping other students by sharing knowledge. This feeling will make it easier for me at times when I feel down because I know that asking questions is welcome and addressing feelings is encouraged!
Being more active and forcing myself to exercise more and to go to yoga classes will help me to relax and calm down and therefore to sleep better and not to get caught in frustration.


WITNESS LIST Defense Affairs & State-Federal Relations Committee April 21, 2005-8:00A HB 1123 On: Streater, Joy (County and District Clerks Association of Texas) HB 2144 For: McKinny, John (Self and American Legion) Squyres, Robert (The American Legion) On: Simmons, Steve (Tx Dept of Transportation) HB 2503 On: Nier, James (Texas Veterans Commission)


Contact
Anyone looking to get in touch with me, the god among men, can reach me by email or by phone. You probably know either or both if you are looking at this site. I can't promise that I will be able to answer all of my fanmail, but I will try my best to at least get through one...per year.


NEXT
Home
Technology
Programming Stuff
Sign Up
NEXT GENERATION
TECHNOLOGY
See what makes us different
Get Started
See what the hype about us
Expirience Bliss
AI Power Technology
Get Started
Are you ready?


class Gem::Resolver::ActivationRequest
Specifies a Specification object that should be activated. Also contains a dependency that was used to introduce this activation.
Attributes
The parent request for this activation request.
The specification to be activated.
Public Class Methods
Creates a new ActivationRequest that
will activate spec
. The parent request
is used
to provide diagnostics in case of conflicts.
others_possible
indicates that other specifications may also
match this activation request.
# File lib/rubygems/resolver/activation_request.rb, line 24 def initialize spec, request, others_possible = true @spec = spec @request = request @others_possible = others_possible end
Public Instance Methods
Is this activation request for a development dependency?
# File lib/rubygems/resolver/activation_request.rb, line 44 def development? @request.development? end
Downloads a gem at path
and returns the file path.
# File lib/rubygems/resolver/activation_request.rb, line 51 def download path Gem.ensure_gem_subdirectories path if @spec.respond_to? :sources exception = nil path = @spec.sources.find{ |source| begin source.download full_spec, path rescue exception end } return path if path raise exception if exception elsif @spec.respond_to? :source source = @spec.source source.download full_spec, path else source = Gem.sources.first source.download full_spec, path end end
The full name of the specification to be activated.
# File lib/rubygems/resolver/activation_request.rb, line 78 def full_name @spec.full_name end
The Gem::Specification for this activation request.
# File lib/rubygems/resolver/activation_request.rb, line 87 def full_spec Gem::Specification === @spec ? @spec : @spec.spec end
True if the requested gem has already been installed.
# File lib/rubygems/resolver/activation_request.rb, line 113 def installed? case @spec when Gem::Resolver::VendorSpecification then true else this_spec = full_spec Gem::Specification.any? do |s| s == this_spec end end end
The name of this activation request's specification
# File lib/rubygems/resolver/activation_request.rb, line 129 def name @spec.name end
Indicate if this activation is one of a set of possible requests for the same Dependency request.
# File lib/rubygems/resolver/activation_request.rb, line 137 def others_possible? case @others_possible when true, false then @others_possible else not @others_possible.empty? end end
Return the ActivationRequest that contained the dependency that we were activated for.
# File lib/rubygems/resolver/activation_request.rb, line 150 def parent @request.requester end
The version of this activation request's specification
# File lib/rubygems/resolver/activation_request.rb, line 181 def version @spec.version end


Farewell, my friends!
Is what I said to my colleagues on Friday! As
this week was my last week at Karmarama
(Accenture Interactive) there were some
farewells. I'll be saying goodbye proper
sometime in the summer when we're allowed out of
the house again!
In my time there I introduced the team to using
Gatsby and styled-components, used Prisma and
the weird client that used render props
(remember render props) for GraphQL queries. I
also sat us all through Egghead videos to learn
about React hooks.
We also created a super slick style guide using
MDX (beta!) other things to note would be an
interactive brocure using Preact and Lottie
animations.
This week
Not a great deal from me this week, I have been
playing around with Svelte and making some notes
on it comparing some patterns to how you would
do the same in React.
Svelte feels really simple, you write html, css
and your JS in the same file and it's super fast
with Vite!
There was another NatterMob on Friday which I
took part in:
🔗 Links
Some useful things I've found this week:
Other links
This is stuff I have found interesting but it's
not directly code related.
Past three newsletters
The puns, are they sufficiently punny? Here are
the last three newsletters:
Peace ✌
Scott


MPI profiling tools.
| Version: |
0.3-1 |
| Depends: |
R (≥ 3.0.0) |
| Imports: |
methods, stats, utils |
| Published: |
2016-09-23 |
| Author: |
Wei-Chen Chen [aut, cre],
Drew Schmidt [aut],
Gaurav Sehrawat [aut],
Pragneshkumar Patel [aut],
George Ostrouchov [aut] |
| Maintainer: |
Wei-Chen Chen <wccsnow at gmail.com> |
| BugReports: |
http://group.r-pbd.org/ |
| License: |
Mozilla Public License 2.0 |
| Copyright: |
See pbdPROF/inst/fpmpi_LICENSE.txt for the files in
src/fpmpi/ and src/fpmpi_win. |
| URL: |
http://r-pbd.org/ |
| NeedsCompilation: |
yes |
| SystemRequirements: |
OpenMPI (>= 1.5.4) on Solaris, Linux, Mac, and
FreeBSD. No MPI library required on Windows yet. |
| Citation: |
pbdPROF citation info |
| Materials: |
README ChangeLog INSTALL |
| In views: |
HighPerformanceComputing |
| CRAN checks: |
pbdPROF results |