Purpose
The loaders that keep his files alive. Every format was specified byte
level in the legacy analysis and verified against real files before a
loader was written. Text arrives as Windows 1252 and is normalised to
UTF-8 on read, numbers are right aligned like RSET STR$, text left
aligned like LSET, and overlong text truncates exactly where his fields
truncated it. Every writer goes through replace_file, the
bytes land in a temporary file beside the target which then takes its
name, so a crash never leaves half a file. File names keep their full
length instead of his eight DOS letters, a new collection gets the .DAT
or .AAF suffix when none is typed, and on Linux a file is found
whatever case its name carries, his twins in capitals as well as a
copied archive in small letters. He knew about the truncation himself
HORCOM, for example, always stores the time only as GMT = UT, remarks are cut off after 51 characters. That still dates from the time when storage space was scarce. Today one can forget about this.
Origin map
| original | ported as | file |
|---|---|---|
Windows 1252 text, _ANSI$(_OEM$()) round trips | cp1252_to_utf8, utf8_to_cp1252 | src/horcom/data/encoding.* |
SPEZIAL\*.DAT, 128 byte records, oeffne20, a201, a2011 | ChartRecord, read_chart_file, write_chart_file | src/horcom/data/chart_file.* |
SPEZ_ORT\*.INT, 36 byte records, the picker zone suffix, ORT.EXT with both encodings | PlaceRecord, read_place_file, read_preferred_place | src/horcom/data/place_file.* |
stat_ausw, stat_ausw_1, bed_erf, bed_erf_asp, haus_def, haus_sel, ze_pl, sum_z_h, stat_ausg_ar | evaluate_statistics, stat_houses, sign_ruler | src/horcom/data/statist_eval.* |
komm_les, lese_text and the ae menu | kommen_entries, read_kommen | src/horcom/data/kommen.* |
TRIM the file, MINIMIZE the file and DELETE records, a2f_tr_dat, minim_dat | trim_records, minimize_records, delete_records | src/horcom/data/chart_file.* |
Overwrite by name, a22ueberschrb | remove_records_by_name | src/horcom/data/chart_file.* |
The chooser sort keys, a210, a211, a211_nnam | RecordOrder, record_order | src/horcom/data/record_order.* |
The AAF twin of a collection, bilde_aaffile$, bilde_horcfile$ | aaf_twin_path, dat_twin_path | src/horcom/data/aaf.* |
The DAT and AAF pair, aaf_horcom2, horcom_aaf3, aaf_ident | chart_record_from_aaf, aaf_export_record, aaf_ident, aaf_same_name, write_dat_from_aaf | src/horcom/data/collection.* |
| The file writes of every routine | read_file_bytes, replace_file, find_case_blind | src/horcom/data/file_io.* |
The statistics output list, bed_erf_1, list_ausg, list_zeil_loe and the vg| table | sort_stat_entries, stat_collation_key, stat_out_of_range | src/horcom/data/statist_list.* |
The chart record
Day, month, astronomical year, hour in Universal Time, minutes with the seconds as fraction, longitude east positive, latitude north positive, then 25 bytes of name, 20 of place and 51 of remark. A remark starting with the calendar flag forces the Julian or the proleptic Gregorian calendar, the loader exposes it as the same Calendar enum the time module uses. There is no header and no index, sorting was always in memory.
Places
Eight bytes longitude, eight latitude, twenty name. The picker files carry the time zone difference in the last five name bytes, stored as the correction that leads from zone time to UT, so CET reads minus one. The preferred place file has two coordinate encodings in the wild, integer micro degrees from the write once writer and plain decimals from older files, the reader takes the original's branch on the missing decimal point including its kk epsilon.
The repository ships his two hand curated zone picker files as
data/places/europa.int and welt.int, the Qt
shell's place search reads any file in that folder plus files opened by
hand, so the full SPEZ_ORT gazetteer of the archive works when copied
in. A data/ort.ext in the original format seeds the startup
coordinates when present. A place picked from a file with a zone fills
the zone field the way his zeitzon box took the zone of a nearby place.
His a2ort itself never touched the time, so the panel keeps the UT of a
fetched or computed record and moves only the clock time, while a clock
time typed before the pick keeps its value and its UT follows the zone.
Privacy rule
His real chart collections contain real people and never enter the repository. The loader tests run on synthetic records written on the fly, the byte layout itself was verified against non personal files, places and settings, during the analysis.
The settings stream
KONSTA7P.INT holds every calculation switch of the program. Its writer
and reader split the fields across lines differently, GFA INPUT ignores
line boundaries, so the loader tokenises the whole file first, quoted
strings with commas inside included. The struct keeps his variable names
as the schema, the mapping onto the pipeline settings follows kon_dhol
with the sixteen to twelve divisor rule of the equal probability mode.
Validated against his real settings file, which showed his own
configuration ran with the topocentric parallax switched on. Its values
live on in code as robert_profile(), verified byte for byte
against the archive file through the writer, and the Qt shell starts on
it, parallax on, true node and true apogee, his own orb table in the
equal probability mode. A konsta file placed next to the data still
overrides the profile, the historical file name included. The shell's
CHANGE HOROSCOPE DEFAULTS dialog edits the live values, orb factor,
maximal divisor, the equal probability mode, the planet weights and the
fixed point, and like his kon_dsp writes them back as konsta.int beside
the data after every change of the defaults and at the end of the
session, so the next start keeps them.
The statistics store
STATIST7 keeps one dataset as three files. The .STA carries 210 byte records, name, place, a packed clock and 34 int32 angles in radians times ten million, the .STH twin adds the six late extras under his naming rule of seven letters of the name plus a 1, and the .PAR parameters give the extra slots their meaning, without it a .STA cannot be read. Two datasets sharing their first seven letters shared his twin, the second overwrote the extras of the first and deleting one took the other's, so the port gives a colliding dataset a twin of its whole base name and spares a shared twin on delete. The loader maps everything onto body slots, detects heliocentric files by the empty Sun beside the zeroed axes, so a dataset computed without houses and angles stays geocentric, and the writer packs byte for byte, pinned by a round trip. Verified locally against his real datasets, over sixteen hundred charts parse with each sun standing where its calendar date demands.
STATISTICS G/H in the EPHEMERIS menu opens his hub, WHAT DO YOU WANT
TO DO ?, with the DEFAULTS, the creation, the evaluation and the
deletion of a dataset, the evaluation preset once a dataset exists. The
DEFAULTS ask whether saved records join the dataset of their file and
whether the list prints SMALL with more details or LARGE, the helio list
stays LARGE. CREATE an EVALUABLE FILE asks PARAMETERS SET
CORRECTLY ?, takes a DAT of the SPEZIAL folder and writes
statist7/<NAME>.STA, .PAR and the
.STH twin, every record with a day and a month computed
with the current settings, the progress in his yellow box while the
program stays locked, ESC or the close button asking REALLY DISCARD
?. Records whose latitude the house system cannot handle are left
out and their number is reported. His DISCARD deleted the .PAR alone
and left a torn .STA, the port removes all three. The .PAR carries his
short house name, App.1, App.2 or Wahr, gen 2 with Maximal and the
parallax as 1 for With and 2 for Without. Once UPDATE NEW RECORDS is
on, a record saved into a DAT offers itself to the dataset of the same
name, computed with the parameters of its .PAR, a record of the same
name is overwritten. His name compare saw the case, the upper case field
never matched a record typed in small letters and every save doubled
it, and his append put the .STH row at record zero, the port compares
without case and appends both files.
The search conditions
stat_ausw runs conditions over a loaded dataset, ported as
evaluate_statistics. The object menu covers a single body, a house
cusp or the ruler of a cusp's sign, the lights, all bodies at once, the
ruler of a house, a midpoint, an aspect between two operands or against
a midpoint, mirror points around both axes, a name fragment and the
arabic parts with their day and night formula swap. The condition menu
places the object at a degree, in a sign, in a house, near another
body or anywhere. Windows that cross the zero point run as extra
passes exactly like his two follow up loops, and In HOUSE with an orb
works for a house that runs over 0° Aries as well. haus_def rebuilds all
twelve cusps from the six the record stores, ze_pl hands each sign its
ruler with the alt switch to the classical ones or the extended set with
Quaoar for Taurus and Chiron for Virgo, Venus and Mercury standing in
where the dataset holds no position of those two, and the aspect
windows share org, orbis_discr and the equal probability multiple
filter with the aspect engine, including his sticky per record flags
under AND. Conditions chain through the mz survivor mask, AND keeps
only records that carried a previous match. SO / MO / AC and ALL
PLANETS read as an OR over their bodies like KOMMSTAT describes them,
his bed_erf kept their mask at the list index and made the group an
AND under AND. sum_z_h tallies every tested value into a sign or house
distribution as the baseline the counts compare against. A SINGLE
ASPECT takes no orb box, its orb is the orbe row of the divisor without
the orb factor, ALL ASPECTS up to DIVISOR runs every divisor up to eight
with the orb factor. The NAME search looks into the padded 25 letter
field, a lone blank lists every name shorter than the field, and the
typed letters count in capitals like the field.
The evaluation screens
START the EVALUATION follows stat2. The dataset opens after his checks, at any size since his cap of 15975 records falls away, a torn .STH or an unreadable file asks for a new dataset, and a file written in the other mode switches the program to heliocentric or geocentric first. Each condition then walks his boxes, n. CHOOSE the OBJECT !, the factor list of ausw_pl_hs with the extras of the dataset, HOUSE NO. and RULER of HOUSE NO. behind their digit boxes, which like the orb box show the condition being built above the question, and SO / MO / AC and ALL PLANETS for the first object only, Where shall the OBJECT be SEARCHED ? with his greyed rows, and the inputs of stat_ausw. * FURTHER CONDITION ? * joins the next one with OR, AND INCLUSIVE or AND EXCLUSIVE or opens the list, up to twelve conditions.
The list keeps his entries, one per match and condition, the name padded to 25 places with the number of the condition, under AND the chain like 1u2u3 in place of the end of the name. INCLUSIVE keeps the earlier entries, EXCLUSIVE cuts the list to the chains, and the entries that end the longest chain print in inverse video. His usuch compared the last digit of the chain alone, from the tenth condition on no chain counted as complete, the port reads the whole number. A list WITHOUT RESTRICTION sorts by the longitude, SO / MO / AC and ALL PLANETS keep their order and every other list sorts by the label with his folding of Ä, Ö, Ü and ß. The page draws his 640 by 480 screen, 24 rows under the grey header, the glyph and position of the match, the name, the moment and in the LARGE list the AC, or the MC when the AC itself was searched, the SMALL list prints the coordinates and SO, MO, AC and MC in decimal degrees. A single condition gets the box of the object and the window and his bars of the sign or house distribution in the element colours, the SO / MO / AC and ALL PLANETS lists included, several get the vertical boxes with the counts and the conditions. His rows printed the last value of a record on every row of it, the port prints the value of each entry. Space turns the page, R turns back, S jumps six pages forward as the footer says, H returns to the first, W asks another condition, the right mouse shows the counts except under WITHOUT RESTRICTION ( 0-360° ), ESC asks END 'STATISTICS' ?. An extra outside its ephemeris file at the date shows dashes and a click names it OUT OF RANGE !. A click on a row opens kotab_sta, DO NOT TAKE OVER shows the chart with the parameters of the dataset until a key, the first time behind his counter box. CANCEL in its CHOOSE SINGLE PLANETS for the CHART ? box keeps the previous selection, the chart still shows and the list returns. The midpoint counter joins the aspect counter only while ADD the MIDPOINT LIST ? answered YES, as in his program. EVALUATE the COUNTER for the WHOLE LIST first shows the clicked chart, then counts every listed record once in a progress window that ESC or the close button stop, and shows the sums over the clicked chart. His counting drew every chart in turn and left the sums over the last one, a chart nobody had chosen. TAKE OVER takes the record into the next RADIX slot with DATA TAKEN OVER FROM the 'STATISTICS' FILE. After the list FURTHER EVALUATION With THIS FILE ? starts over, ends or returns to the list. A search without a match says NO record MEETS ALL CONDITIONS !, marks the condition DUD and goes straight on to the next evaluation without an empty list page.
The commentary texts
The KOMMEN7P folder holds Robert Rettig's own German essays, an introduction and commentaries on input, the ephemeris, the chart types, solars, the Munich Rhythm Theory, directions, houses, statistics, the AAF world and assorted notes, plus the change log and the short manual at the program root. They are not an interpretation engine, the original had none, they are his writing shown in the READ TEXT FILE box. The texts ship with the repository in data/kommen as markdown editions, published by his family with the wording unchanged, only reflowed and curated, one private postal address of a third person removed, the parts behind his mid file separators included that the original reader always stopped at, and the era bound passages about installation, printer control and crash recovery of the historical program left out. The shell opens them from the EXPLANATION entries at the end of every menu, from F1 inside an output and from ABOUT HORCOM. His byte exact text files still work, the ported lese_text rules read them, tilde lines and overlong lines drop, a leading dash ends the file, the bytes decode from Windows 1252, and a folder picker in the dialog opens an original KOMMEN7P folder kept anywhere else.
The AAF exchange format
The tagged text format is the port archive format going forward. The parser takes the original quirks whole, the tilde as universal ignore marker, stars as empty fields, HTML stripped so saved web pages still parse, plain lines continuing a comment, the calendar suffix on the year and the rule that a Julian date outranks the clock fields. The writer reproduces the A93 and B93 lines of make_aaf including STR$(jd,13,5). The shell writes real records through it, the record mask carries the person, the place name, the country abbreviation and the summer time code of the original sommerzeit table, the clock stays civil with the zone string beside it composed like zeitzon, and saving into an existing file can append to the collection instead of replacing it. In the AAF box OK = Save writes into an AAF file, by default the twin of the working data file, asks before it overwrites a record of the same name and rebuilds the matching DAT like aaf_horcom2. Entering the chart type, country, summer time or zone field opens the pick list of hor_art, laender, sommerzeit or the zone catalogue. His same name rule of a22dat held only at radix level, so a derived chart, a SOLAR, a COMBINE or a result taken as radix, joins the data file beside the birth record and never replaces it. His question for a record of the same name, OVERWRITE, SAVE the record IN ADDITION or CANCEL, held for a DAT file alone, beside an AAF twin a22dat replaced the AAF record without asking. The tester wanted the second record there as well, so the same three answers now stand for both. OVERWRITE removes every AAF record of the name like a22ueberschrb drops every DAT record of it, with the star rule of aaf_ident as the fallback, before the new one joins at the end, IN ADDITION keeps both, and the DAT follows the AAF file. Record lists and place lists sort an umlaut like its base vowel. CHAIN FILES carries his chaining tool daterw over, the way he merged collections for the statistics work. The records of the files called one after another, DAT or AAF, join his chain file AA_MUDAT.DAT in SPEZIAL with day and month, chain_append in src/horcom/data/collection.*, and END CHAINING runs the trim pass over it. The same box deletes or renames the chain file. SPEZIAL is found in any letter case, so the evaluation file of the statistics finds the chain on a case sensitive system too. The AAF to HORCOM conversion presses exchange records into the fixed 128 byte layout with the Julian flag on the remark, and his two maintenance passes survive as TRIM the file, empty records out and leading blanks off the names, and MINIMIZE the file, duplicates of name and birth clock collapsed, MINIMIZE through a hash set where his pass compared every record with all before it. The collections browser and DELETE records remove any number of marked records and write the file back, his DELETE took ten at a time, the size of his mark array.
The country tables
landnima.int names the two letter NIMA prefixes of the big place files, 263 code lines in the shape XX = NAME, and the shell's place search uses it to label the files with their countries. One documented deviation, the original discriminator starts behind its first array slot and can never match Aruba, the rewrite searches every entry. laender.int carries the 57 German auto style abbreviations of the record mask behind its header row, loaded and pinned for the record editor to come. Both ship as seeds in data.
The zone name catalogue
His zonnamen.int lists 176 named zones behind the header row, credited
in the original dialog title as public domain via B. Mahl. Fixed column
text, the name to column 46, the abbreviation from column 47, the last
ten characters the difference from zone time to UT in the shape minus
eleven h twenty three m. The sign lives only in the first character
because VAL of the hour field drops it, the parser keeps exactly that
arithmetic. The LMT and LTT rows carry no number, there local time
follows from the longitude. In the AAF box LMT takes the clock straight
from the longitude, and LTT turns true into mean local time with the
equation of time like his zuo, on its own before 1810 and after his
question until 1890. The catalogue ships as
data/zonnamen.int and the shell's zone picker reads it,
still under his dialog title.
Verification
test_data.cpp pins the 1252 round trip including the high
row, the exact field offsets and alignments of an encoded chart record,
file round trips with a BC year and the Julian flag, rejection of torn
files, the place layout, the zone suffix readings for east and west, and
both preferred place encodings. The shipped europa picker is pinned to
its 465 places with Agram at minus one, and his profile is pinned on
every switch and round trips through the writer and reader unchanged.
test_statist_eval.cpp runs invented charts through every object
and window, the cusp mirroring, the twelve rulers with the alt switch,
the zero wrap, the aspect fold with the multiple filter, the AND
survivors and the mask silence of the collective walks.