From eef9bbd2d8f52443eb9711804ba03fc00af8ee23 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Mon, 28 Aug 2023 09:04:28 -0400 Subject: move *.hs to src/ --- CosmicCalendar.hs | 140 ------ CosmicCalendarEvents.hs | 1012 ------------------------------------------- countdown.hs | 523 ---------------------- package.yaml | 1 + src/CosmicCalendar.hs | 140 ++++++ src/CosmicCalendarEvents.hs | 1012 +++++++++++++++++++++++++++++++++++++++++++ src/countdown.hs | 523 ++++++++++++++++++++++ 7 files changed, 1676 insertions(+), 1675 deletions(-) delete mode 100644 CosmicCalendar.hs delete mode 100644 CosmicCalendarEvents.hs delete mode 100755 countdown.hs create mode 100644 src/CosmicCalendar.hs create mode 100644 src/CosmicCalendarEvents.hs create mode 100755 src/countdown.hs diff --git a/CosmicCalendar.hs b/CosmicCalendar.hs deleted file mode 100644 index db29c02..0000000 --- a/CosmicCalendar.hs +++ /dev/null @@ -1,140 +0,0 @@ -{-# OPTIONS_GHC - -Wall - -Wno-unused-imports - -Wno-unused-top-binds - -Wno-name-shadowing -#-} -{-# language NoImplicitPrelude #-} -{-# language RecordWildCards #-} -{-# language FlexibleContexts #-} -{-# language TemplateHaskell #-} -{-# language ViewPatterns #-} -{-# language OverloadedStrings #-} -{-# language QuasiQuotes #-} - -module CosmicCalendar where - -import Rebase.Prelude -import qualified Rebase.Prelude as Prelude -import Control.Lens hiding ((<|)) -import Data.Foldable (toList) -import Data.Ratio -import Text.Printf -import Data.Time.Calendar.OrdinalDate -import Data.Time.LocalTime -import Control.Monad.RWS -import Data.Time.Calendar.OrdinalDate -import Data.Text.Format.Numbers -import NeatInterpolation -import qualified Data.Text as Text -import Data.Text (Text, pack, unpack) - -import Rebase.Data.Map.Strict (Map) -import qualified Rebase.Data.Map.Strict as Map - --- 13.787±0.020 billion years. Source: https://en.wikipedia.org/wiki/Age_of_the_universe#cite_note-Planck_2018-2 -ageOfUniverseInYears :: Integer -ageOfUniverseInYears = 13787 * 1000 * 1000 - --- The point of the cosmic calendar is to mentally visualize or model the scale --- of cosmic/geologic/evolutionary events using the existing internal mental --- model of the year. This internal mental model of the year is NOT a 365.2422 --- day earth rotation, but a 365 day calendar year. --- --- In order to make the math of the calendar work out, the functions that look --- up calendary entries (and take as input the LocalTime) must check for leap --- year, and subtract one day from the input if it is later than February. -daysPerYear :: NominalDiffTime -daysPerYear = 365 -- NOT 365.2422 - -lengthOfDay :: NominalDiffTime -lengthOfDay = 24 * 60 * 60 - -lengthOfYear :: NominalDiffTime -lengthOfYear = daysPerYear * lengthOfDay - -ageOfUniverse :: NominalDiffTime -ageOfUniverse = fromIntegral ageOfUniverseInYears * lengthOfYear - -data CalendarEntry = CalendarEntry { - calBeginTime :: NominalDiffTime, - calEndTime :: Maybe NominalDiffTime, - calTitle :: Text, - calSubtitle :: Text, - calDescription :: Text, - calReferences :: Text -} deriving (Show) - --- TODO: Encode the input times like so: --- --- data CosmicTime = YearsAgo Rational | YearsAfterBigBang Rational | YearsBCE Rational | YearsCE Rational --- --- The absolute time values (YearsBCE and YearsCE) will be computed using the --- year at program start: - -currentYear :: Integer -currentYear = unsafePerformIO $ getZonedTime <&> toGregorian . localDay . zonedTimeToLocalTime <&> view _1 - -years :: Rational -> NominalDiffTime -years = (* lengthOfYear) . fromRational - -yearsAgo :: Rational -> NominalDiffTime -yearsAgo (fromRational -> n) = lengthOfYear * (1 - (n / fromIntegral ageOfUniverseInYears)) - -afterBigBang :: NominalDiffTime -> NominalDiffTime -afterBigBang = (/ ageOfUniverse) . (* lengthOfYear) - -thousandYears :: Rational -> NominalDiffTime -thousandYears = years . (* 1000) - -millionYears :: Rational -> NominalDiffTime -millionYears = thousandYearsAgo . (* 1000) - -billionYears :: Rational -> NominalDiffTime -billionYears = millionYearsAgo . (* 1000) - -thousandYearsAgo :: Rational -> NominalDiffTime -thousandYearsAgo = yearsAgo . (* 1000) - -millionYearsAgo :: Rational -> NominalDiffTime -millionYearsAgo = thousandYearsAgo . (* 1000) - -billionYearsAgo :: Rational -> NominalDiffTime -billionYearsAgo = millionYearsAgo . (* 1000) - -yearStart :: LocalTime -> LocalTime -yearStart (LocalTime d _) = LocalTime d' t' - where - d' = fromGregorian y 1 1 - t' = TimeOfDay 0 0 0 - (y, _, _) = toGregorian d - -localTimeToYearElapsed :: LocalTime -> NominalDiffTime -localTimeToYearElapsed t = t `diffLocalTime` yearStart t - -getPreviousCalendarEntry :: Calendar -> LocalTime -> Maybe CalendarEntry -getPreviousCalendarEntry cal (localTimeToYearElapsed -> t) = snd <$> Map.lookupLT t cal - -getCurrentCalendarEntry :: Calendar -> LocalTime -> Maybe CalendarEntry -getCurrentCalendarEntry cal (localTimeToYearElapsed -> t) = snd <$> Map.lookupLE t cal - -type Calendar = Map NominalDiffTime CalendarEntry - -getNextCalendarEntry :: Calendar -> LocalTime -> Maybe CalendarEntry -getNextCalendarEntry cal (localTimeToYearElapsed -> t) = snd <$> Map.lookupGT t cal - -buildCalendar :: [CalendarEntry] -> Map NominalDiffTime CalendarEntry -buildCalendar ls = Map.fromList $ map (\x -> (calBeginTime x, x)) $ map unwrap ls - -unwrap :: CalendarEntry -> CalendarEntry -unwrap x@CalendarEntry{..} = x { calDescription = unwrapText calDescription } - where - unwrapText :: Text -> Text - unwrapText = pack . unlines . map unwords . foldr process [] . lines . unpack - process line [] = [[line]] - process line ((x:xs):ys) | shouldMerge line x = (line:x:xs):ys - process line rest = [line]:rest - shouldMerge :: String -> String -> Bool - shouldMerge "" _ = False - shouldMerge _ "" = False - shouldMerge _ _ = True diff --git a/CosmicCalendarEvents.hs b/CosmicCalendarEvents.hs deleted file mode 100644 index 90b5848..0000000 --- a/CosmicCalendarEvents.hs +++ /dev/null @@ -1,1012 +0,0 @@ -{-# OPTIONS_GHC -Wall #-} -{-# language NoImplicitPrelude #-} -{-# language OverloadedStrings #-} -{-# language QuasiQuotes #-} - -module CosmicCalendarEvents where - -import Rebase.Prelude -import NeatInterpolation - -import CosmicCalendar - -theYear, yearsBeforeCommonEra :: Integer -> NominalDiffTime -theYear = yearsAgo . toRational . (currentYear -) -yearsBeforeCommonEra = yearsAgo . toRational . ((+) (currentYear - 1)) - -theCalendar :: Map NominalDiffTime CalendarEntry -theCalendar = buildCalendar $ - [ - CalendarEntry 0 - Nothing - "The Big Bang" - "The universe begins" - "" - "", - - CalendarEntry (370 & thousandYears & afterBigBang) - Nothing - "Recombination" - "The universe becomes transparent" - [text| - At about 370,000 years,[3][4][5][6] neutral hydrogen atoms finish forming - ("recombination"), and as a result the universe also became transparent for - the first time. The newly formed atoms—mainly hydrogen and helium with - traces of lithium—quickly reach their lowest energy state (ground state) by - releasing photons ("photon decoupling"), and these photons can still be - detected today as the cosmic microwave background (CMB). This is the oldest - direct observation we currently have of the universe. - |] - [text| - https://en.wikipedia.org/wiki/Chronology_of_the_universe#The_very_early_universe - - 3. Tanabashi, M. 2018, p. 358, chpt. 21.4.1: "Big-Bang Cosmology" (Revised - September 2017) by Keith A. Olive and John A. Peacock. - - 4. Notes: Edward L. Wright's Javascript Cosmology Calculator (last modified - 23 July 2018). With a default H 0 {\displaystyle H_{0}} H_{0} = 69.6 (based - on WMAP9+SPT+ACT+6dFGS+BOSS/DR11+H0/Riess) parameters, the calculated age of - the universe with a redshift of z = 1100 is in agreement with Olive and - Peacock (about 370,000 years). - - 5. Hinshaw, Weiland & Hill 2009. See PDF: page 45, Table 7, Age at - decoupling, last column. Based on WMAP+BAO+SN parameters, the age of - decoupling occurred 376971+3162−3167 years after the Big Bang. - - 6. Ryden 2006, pp. 194–195. "Without going into the details of the - non-equilibrium physics, let's content ourselves by saying, in round - numbers, zdec ≈ 1100, corresponding to a temperature Tdec ≈ 3000 K, when the - age of the universe was tdec ≈ 350,000 yr in the Benchmark Model. (...) The - relevant times of various events around the time of recombination are shown - in Table 9.1. (...) Note that all these times are approximate, and are - dependent on the cosmological model you choose. (I have chosen the Benchmark - Model in calculating these numbers.)" - - https://en.wikipedia.org/wiki/Recombination_(cosmology)#cite_note-2 - |], - - CalendarEntry (13.4 & billionYearsAgo) Nothing - "The first observed star" - "" - "First Light Viewed Through the Rich Cluster Abell 2218" - "https://sites.astro.caltech.edu/~rse/firstlight/", - - CalendarEntry (4.6 & billionYearsAgo) Nothing - "Formation of the Sun" - "The formation of the solar system begins" - [text| - The formation of the Solar System began about 4.6 billion years ago with the - gravitational collapse of a small part of a giant molecular cloud.[1] Most - of the collapsing mass collected in the center, forming the Sun, while the - rest flattened into a protoplanetary disk out of which the planets, moons, - asteroids, and other small Solar System bodies formed. - |] - "https://en.wikipedia.org/wiki/Formation_and_evolution_of_the_Solar_System", - - CalendarEntry (4.54 & billionYearsAgo) Nothing - "Formation of Earth" - "" - [text| - The standard model for the formation of the Solar System (including the - Earth) is the solar nebula hypothesis.[23] In this model, the Solar System - formed from a large, rotating cloud of interstellar dust and gas called the - solar nebula. It was composed of hydrogen and helium created shortly after - the Big Bang 13.8 Ga (billion years ago) and heavier elements ejected by - supernovae. About 4.5 Ga, the nebula began a contraction that may have been - triggered by the shock wave from a nearby supernova.[24] A shock wave would - have also made the nebula rotate. As the cloud began to accelerate, its - angular momentum, gravity, and inertia flattened it into a protoplanetary - disk perpendicular to its axis of rotation. Small perturbations due to - collisions and the angular momentum of other large debris created the means - by which kilometer-sized protoplanets began to form, orbiting the nebular - center.[25] - - The center of the nebula, not having much angular momentum, collapsed - rapidly, the compression heating it until nuclear fusion of hydrogen into - helium began. After more contraction, a T Tauri star ignited and evolved - into the Sun. Meanwhile, in the outer part of the nebula gravity caused - matter to condense around density perturbations and dust particles, and the - rest of the protoplanetary disk began separating into rings. In a process - known as runaway accretion, successively larger fragments of dust and debris - clumped together to form planets.[25] Earth formed in this manner about 4.54 - billion years ago (with an uncertainty of 1%)[26][27][4] and was largely - completed within 10–20 million years.[28] The solar wind of the newly formed - T Tauri star cleared out most of the material in the disk that had not - already condensed into larger bodies. The same process is expected to - produce accretion disks around virtually all newly forming stars in the - universe, some of which yield planets.[29] - |] - "https://en.wikipedia.org/wiki/History_of_Earth#Solar_System_formation", - - CalendarEntry (8.8 & billionYearsAgo) Nothing - "Thin disk of the Milky Way Galaxy" - "Our galaxy begins to form" - [text| - The age of stars in the galactic thin disk has also been estimated using - nucleocosmochronology. Measurements of thin disk stars yield an estimate - that the thin disk formed 8.8 ± 1.7 billion years ago. These measurements - suggest there was a hiatus of almost 5 billion years between the formation - of the galactic halo and the thin disk.[253] Recent analysis of the chemical - signatures of thousands of stars suggests that stellar formation might have - dropped by an order of magnitude at the time of disk formation, 10 to 8 - billion years ago, when interstellar gas was too hot to form new stars at - the same rate as before.[254] - |] - "", - - CalendarEntry (4.4 & billionYearsAgo) Nothing - "Formation of the moon" - "A collision of the planet Theia with Earth creates the moon" - [text| - Astronomers think the collision between Earth and Theia happened at about - 4.4 to 4.45 bya; about 0.1 billion years after the Solar System began to - form.[15][16] In astronomical terms, the impact would have been of moderate - velocity. Theia is thought to have struck Earth at an oblique angle when - Earth was nearly fully formed. Computer simulations of this "late-impact" - scenario suggest an initial impactor velocity at infinity below 4 kilometres - per second (2.5 mi/s), increasing as it fell to over 9.3 km/s (5.8 mi/s) at - impact, and an impact angle of about 45°.[17] However, oxygen isotope - abundance in lunar rock suggests "vigorous mixing" of Theia and Earth, - indicating a steep impact angle.[3][18] Theia's iron core would have sunk - into the young Earth's core, and most of Theia's mantle accreted onto - Earth's mantle. However, a significant portion of the mantle material from - both Theia and Earth would have been ejected into orbit around Earth (if - ejected with velocities between orbital velocity and escape velocity) or - into individual orbits around the Sun (if ejected at higher velocities). - Modelling[19] has hypothesised that material in orbit around Earth may have - accreted to form the Moon in three consecutive phases; accreting first from - the bodies initially present outside Earth's Roche limit, which acted to - confine the inner disk material within the Roche limit. The inner disk - slowly and viscously spread back out to Earth's Roche limit, pushing along - outer bodies via resonant interactions. After several tens of years, the - disk spread beyond the Roche limit, and started producing new objects that - continued the growth of the Moon, until the inner disk was depleted in mass - after several hundreds of years. - |] - [text| - https://en.wikipedia.org/wiki/Giant-impact_hypothesis#Basic_model - https://www.psi.edu/epo/moon/moon.html - |], - - CalendarEntry (3.77 & billionYearsAgo) Nothing - "Life on Earth" - "" - [text| - The earliest time for the origin of life on Earth is at least 3.77 billion - years ago, possibly as early as 4.28 billion years,[2] or even 4.41 billion - years[4][5]—not long after the oceans formed 4.5 billion years ago, and - after the formation of the Earth 4.54 billion years ago.[2][3][6][7] - |] - "https://en.wikipedia.org/wiki/Earliest_known_life_forms", - - CalendarEntry (3.42 & billionYearsAgo) Nothing - "Earliest known life on Earth" - "The fossil record begins" - [text| - The earliest known life forms on Earth are putative fossilized - microorganisms found in hydrothermal vent precipitates, considered to be - about 3.42 billion years old.[1][2] The earliest time for the origin of life - on Earth is at least 3.77 billion years ago, possibly as early as 4.28 - billion years,[2] or even 4.41 billion years[4][5]—not long after the oceans - formed 4.5 billion years ago, and after the formation of the Earth 4.54 - billion years ago.[2][3][6][7] The earliest direct evidence of life on Earth - is from microfossils of microorganisms permineralized in - 3.465-billion-year-old Australian Apex chert rocks.[8][9] - |] - "https://en.wikipedia.org/wiki/Earliest_known_life_forms", - - CalendarEntry (3.4 & billionYearsAgo) Nothing - "First photosynthetic bacteria" - "(Still no Oxygen)" - [text| - They absorbed near-infrared rather than visible light and produced sulfur or - sulfate compounds rather than oxygen. Their pigments (possibly - bacteriochlorophylls) were predecessors to chlorophyll. - |] - "https://www.scientificamerican.com/article/timeline-of-photosynthesis-on-earth/", - - CalendarEntry (2.7 & billionYearsAgo) Nothing - "Oxygen from photosynthesis" - [text| - Cyanobacteria (blue-green algae) initiates "rusting of the Earth" - The resulting Ozone layer will make life possible on land - |] - [text| - These ubiquitous bacteria were the first oxygen producers. They absorb - visible light using a mix of pigments: phycobilins, carotenoids and several - forms of chlorophyll. - - The Great Oxidation Event (GOE), also called the Great Oxygenation Event, - the Oxygen Catastrophe, the Oxygen Revolution, and the Oxygen Crisis, was a - time interval when the Earth's atmosphere and the shallow ocean first - experienced a rise in the amount of oxygen. This occurred approximately - 2.4–2.0 Ga (billion years) ago, during the Paleoproterozoic era.[2] - Geological, isotopic, and chemical evidence suggests that - biologically-produced molecular oxygen (dioxygen, O2) started to accumulate - in Earth's atmosphere and changed it from a weakly reducing atmosphere - practically free of oxygen into an oxidizing atmosphere containing abundant - oxygen.[3] - - The sudden injection of toxic oxygen into an anaerobic biosphere caused the - extinction of many existing anaerobic species on Earth.[4] Although the event is - inferred to have constituted a mass extinction,[5] due in part to the great - difficulty in surveying microscopic species' abundances, and in part to the - extreme age of fossil remains from that time, the Oxygen Catastrophe is - typically not counted among conventional lists of "great extinctions", which are - implicitly limited to the Phanerozoic eon. - - The event is inferred to have been caused by cyanobacteria producing the - oxygen, which may have enabled the subsequent development of multicellular - life-forms.[6] - - The current scientific understanding of when and how the Earth's atmosphere - changed from a weakly reducing to a strongly oxidizing atmosphere largely - began with the work of the American geologist Preston Cloud in the 1970s.[9] - Cloud observed that detrital sediments older than about 2 billion years ago - contained grains of pyrite, uraninite,[9] and siderite,[12] all minerals - containing reduced forms of iron or uranium that are not found in younger - sediments because they are rapidly oxidized in an oxidizing atmosphere. He - further observed that continental redbeds, which get their color from the - oxidized (ferric) mineral hematite, began to appear in the geological record - at about this time. Banded iron formation largely disappears from the - geological record at 1.85 billion years ago, after peaking at about 2.5 - billion years ago.[14] Banded iron formation can form only when abundant - dissolved ferrous iron is transported into depositional basins, and an - oxygenated ocean blocks such transport by oxidizing the iron to form - insoluble ferric iron compounds.[15] The end of the deposition of banded - iron formation at 1.85 billion years ago is therefore interpreted as marking - the oxygenation of the deep ocean.[9] Heinrich Holland further elaborated - these ideas through the 1980s, placing the main time interval of oxygenation - between 2.2 and 1.9 billion years ago, and they continue to shape the - current scientific understanding.[10] - |] - [text| - https://www.scientificamerican.com/article/timeline-of-photosynthesis-on-earth/ - https://en.wikipedia.org/wiki/Great_Oxidation_Event - |], - - CalendarEntry (2.05 & billionYearsAgo) Nothing - "Eukaryotic cells" - "Cells with nucleus (inner membrane holding DNA)" - [text| - Eukaryotes (/juːˈkærioʊts, -əts/) are organisms whose cells have a nucleus - enclosed within a nuclear envelope.[1][2][3] They belong to the group of - organisms Eukaryota or Eukarya; their name comes from the Greek εὖ (eu, - "well" or "good") and κάρυον (karyon, "nut" or "kernel").[4] The domain - Eukaryota makes up one of the three domains of life; bacteria and archaea - (both prokaryotes) make up the other two domains.[5][6] The eukaryotes are - usually now regarded as having emerged in the Archaea or as a sister of the - Asgard archaea.[7][8] This implies that there are only two domains of life, - Bacteria and Archaea, with eukaryotes incorporated among archaea.[9][10] - Eukaryotes represent a small minority of the number of organisms;[11] - however, due to their generally much larger size, their collective global - biomass is estimated to be about equal to that of prokaryotes.[11] - Eukaryotes emerged approximately 2.3–1.8 billion years ago, during the - Proterozoic eon, likely as flagellated phagotrophs.[12][13] - |] - "https://en.wikipedia.org/wiki/Eukaryote", - - CalendarEntry (1.2 & billionYearsAgo) Nothing - "Red and brown algae" - "" - [text| - These organisms have more complex cellular structures than bacteria do. Like - cyanobacteria, they contain phycobilin pigments as well as various forms of - chlorophyll. - |] - "https://www.scientificamerican.com/article/timeline-of-photosynthesis-on-earth/", - - CalendarEntry (0.75 & billionYearsAgo) Nothing - "Green algae" - "" - [text| - Green algae do better than red and brown algae in the strong light of - shallow water. They make do without phycobilins. - |] - "https://www.scientificamerican.com/article/timeline-of-photosynthesis-on-earth/", - - CalendarEntry (0.475 & billionYearsAgo) Nothing - "First land plants" - "" - [text| - Mosses and liverworts descended from green algae. Lacking vascular structure - (stems and roots) to pull water from the soil, they are unable to grow - tall. - |] - "https://www.scientificamerican.com/article/timeline-of-photosynthesis-on-earth/", - - CalendarEntry (0.423 & billionYearsAgo) Nothing - "Vascular plants" - "" - [text| - These are literally garden-variety plants, such as ferns, grasses, trees and - cacti. They are able to grow tall canopies to capture more light. - |] - "https://www.scientificamerican.com/article/timeline-of-photosynthesis-on-earth/", - - CalendarEntry (750 & millionYearsAgo) Nothing - "Bones and shells" - "" - [text| - A series of spectacularly preserved, 750-million-year-old fossils represent - the microscopic origins of biomineralization, or the ability to convert - minerals into hard, physical structures. This process is what makes bones, - shells, teeth and hair possible, literally shaping the animal kingdom and - even Earth itself. - - The fossils were pried from ancient rock formations in Canada's Yukon by - earth scientists Francis Macdonald and Phoebe Cohen of Harvard University. - In a June Geology paper, they describe their findings as providing "a unique - window into the diversity of early eukaryotes." - - Using molecular clocks and genetic trees to reverse-engineer evolutionary - histories, previous research placed the beginning of biomineralization at - about 750 million years ago. Around that time, the fossil record gets - suggestive, turning up vase-shaped amoebas with something like scales in - their cell walls, algae with cell walls possibly made from calcium carbonate - and sponge-like creatures with seemingly mineralized bodies. - |] - "https://www.wired.com/2011/06/first-shells/", - - CalendarEntry (440 & millionYearsAgo) Nothing - "Fish with jaws" - "" - [text| - Prehistoric armoured fishes called placoderms were the first fishes to have - jaws. They arose some time in the Silurian Period, about 440 million years - ago, to become the most abundant and diverse fishes of their day. - - Placoderms dominated the oceans, rivers and lakes for some 80 million years, - before their sudden extinction around 359 million years ago. This is possibly - due to the depletion of trace elements in our oceans. - |] - "", - - CalendarEntry (518 & millionYearsAgo) Nothing - "Vertebrates" - "Animals with backbones" - [text| - Vertebrates (/ˈvɜːrtəbrɪts, -ˌbreɪts/)[3] comprise all animal taxa within - the subphylum Vertebrata (/ˌvɜːrtəˈbreɪtə/)[4] (chordates with backbones), - including all mammals, birds, reptiles, amphibians, and fish. Vertebrates - represent the overwhelming majority of the phylum Chordata, with currently - about 69,963 species described.[5] - |] - "", - - CalendarEntry (385 & millionYearsAgo) Nothing - "Insects" - "" - [text| - Comprising up to 10 million living species, insects today can be found on - all seven continents and inhabit every terrestrial niche imaginable. But - according to the fossil record, they were scarce before about 325 million - years ago, outnumbered by their arthropod cousins the arachnids (spiders, - scorpions and mites) and myriapods (centipedes and millipedes). - - The oldest confirmed insect fossil is that of a wingless, silverfish-like - creature that lived about 385 million years ago. It’s not until about 60 - million years later, during a period of the Earth’s history known as the - Pennsylvanian, that insect fossils become abundant. - |] - "https://earth.stanford.edu/news/insects-took-when-they-evolved-wings", - - CalendarEntry (368 & millionYearsAgo) Nothing - "Amphibians" - "" - [text| - The earliest well-known amphibian, Ichthyostega, was found in Late Devonian - deposits in Greenland, dating back about 363 million years. The earliest - amphibian discovered to date is Elginerpeton, found in Late Devonian rocks - of Scotland dating to approximately 368 million years ago. The later - Paleozoic saw a great diversity of amphibians, ranging from small legless - swimming forms (Aistopoda) to bizarre "horned" forms (Nectridea). Other - Paleozoic amphibians more or less resembled salamanders outwardly but - differed in details of skeletal structure. Exactly how to classify these - fossils, and how they might be related to living amphibians, is still - debated by paleontologists. Shown at the right is Phlegethontia, an aistopod - from the Pennsylvanian. - - The familiar frogs, toads, and salamanders have been present since at least - the Jurassic Period. (The fossil frog pictured to the left is much younger, - coming from the Eocene, only 45 to 55 million years ago). Fossil caecilians - are very rare; until recently the oldest known caecilians were Cenozoic in - age (that is, less than 65 million years old), but recent finds have pushed - back the ancestry of the legless caecilians to Jurassic ancestors that had - short legs. The rarity of fossil caecilians is probably due to their - burrowing habitat and reduced skeleton, both of which lessen the chances of - preservation. - |] - "https://ucmp.berkeley.edu/vertebrates/tetrapods/amphibfr.html", - - CalendarEntry (320 & millionYearsAgo) Nothing - "Reptiles" - "" - [text| - Reptiles, in the traditional sense of the term, are defined as animals that - have scales or scutes, lay land-based hard-shelled eggs, and possess - ectothermic metabolisms. - - Though few reptiles today are apex predators, many examples of apex reptiles - have existed in the past. Reptiles have an extremely diverse evolutionary - history that has led to biological successes, such as dinosaurs, pterosaurs, - plesiosaurs, mosasaurs, and ichthyosaurs. - |] - [text| - https://en.wikipedia.org/wiki/Evolution_of_reptiles - https://www.thoughtco.com/the-first-reptiles-1093767 - |], - - CalendarEntry (335 & millionYearsAgo) Nothing - "Pangea forms" - "" - [text| - Pangaea or Pangea (/pænˈdʒiː.ə/)[1] was a supercontinent that existed during - the late Paleozoic and early Mesozoic eras.[2] It assembled from the earlier - continental units of Gondwana, Euramerica and Siberia during the - Carboniferous approximately 335 million years ago, and began to break apart - about 200 million years ago, at the end of the Triassic and beginning of the - Jurassic.[3] In contrast to the present Earth and its distribution of - continental mass, Pangaea was centred on the Equator and surrounded by the - superocean Panthalassa and the Paleo-Tethys and subsequent Tethys Oceans. - Pangaea is the most recent supercontinent to have existed and the first to - be reconstructed by geologists. - |] - "https://en.wikipedia.org/wiki/Pangaea", - - CalendarEntry (243 & millionYearsAgo) Nothing - "Dinosaurs" - "" - [text| - For the past twenty years, Eoraptor has represented the beginning of the Age - of Dinosaurs. This controversial little creature–found in the roughly - 231-million-year-old rock of Argentina–has often been cited as the earliest - known dinosaur. But Eoraptor has either just been stripped of that title, or - soon will be. A newly-described fossil found decades ago in Tanzania extends - the dawn of the dinosaurs more than 10 million years further back in time. - - Named Nyasasaurus parringtoni, the roughly 243-million-year-old fossils - represent either the oldest known dinosaur or the closest known relative to - the earliest dinosaurs. The find was announced by University of Washington - paleontologist Sterling Nesbitt and colleagues in Biology Letters, and I - wrote a short news item about the discovery for Nature News. The paper - presents a significant find that is also a tribute to the work of Alan - Charig–who studied and named the animal, but never formally published a - description–but it isn’t just that. The recognition of Nyasasaurus right - near the base of the dinosaur family tree adds to a growing body of evidence - that the ancestors of dinosaurs proliferated in the wake of a catastrophic - mass extinction. - |] - [text| - https://www.smithsonianmag.com/science-nature/scientists-discover-oldest-known-dinosaur-152807497/ - |], - - CalendarEntry (210 & millionYearsAgo) Nothing - "Mammals" - "" - [text| - The earliest known mammals were the morganucodontids, tiny shrew-size - creatures that lived in the shadows of the dinosaurs 210 million years ago. - They were one of several different mammal lineages that emerged around that - time. All living mammals today, including us, descend from the one line that - survived. - |] - "https://www.nationalgeographic.com/science/article/rise-mammals", - - CalendarEntry (150 & millionYearsAgo) Nothing - "Birds" - "" - [text| - The first birds had sharp teeth, long bony tails and claws on their hands. - The clear distinction we see between living birds and other animals did not - exist with early birds. The first birds were in fact more like small - dinosaurs than they were like any bird today. - - The earliest known (from fossils) bird is the 150-million-year-old - Archaeopteryx, but birds had evolved before then. A range of birds with more - advanced features appeared soon after Archaeopteryx. One group gave rise to - modern birds in the Late Cretaceous. - |] - "https://australian.museum/learn/dinosaurs/the-first-birds/", - - CalendarEntry (130 & millionYearsAgo) Nothing - "Flowers" - "" - [text| - Today, plants with flowers--called angiosperms--dominate the landscape. - Around 80 percent of green plants alive today, from oak trees to grass, are - flowering plants. In all of these plants, flowers are part of the - reproductive system. But 130 million years ago, flowering plants were rare. - Most plants reproduced with spores, found today on ferns, or with seeds and - cones, found today on pine trees. The plant fossils found in Liaoning, - China, show evidence of plants with spores or seeds--and perhaps one of the - first flowering plants. - - Researchers have found an ancient plant in Liaoning, Archaefructus, that has - very small, simple flowers and could be one of the first flowering plants. - Archaefructus lived around 130 million years ago and probably grew in or - near the water. - |] - "https://www.amnh.org/exhibitions/dinosaurs-ancient-fossils/liaoning-diorama/when-flowers-first-bloomed", - - CalendarEntry (85 & millionYearsAgo) Nothing - "Tyranosaurids" - "The Tyrant Lizards" - [text| - The name says it all. This group of huge carnivores must have tyrannically - ruled the land during the last part of the Cretaceous, 85 to 65 million - years ago. Short but deep jaws with banana-sized sharp teeth, long hind - limbs, small beady eyes, and tiny forelimbs (arms) typify a tyrannosaur. The - Tyrannosauridae included such similar animals (in rough order of increasing - size) as Albertosaurus, Gorgosaurus, Daspletosaurus, Tarbosaurus, and of - course Tyrannosaurus rex. - - T. rex was one of the largest terrestrial carnivores of all time. It stood - approximately 15 feet high and was about 40 feet in length, roughly six tons - in weight. In its large mouth were six-inch long, sharp, serrated teeth. - - Just about two dozen good specimens of these animals have been found and - these finds are from highly restricted areas in western North America. Henry - Fairfield Osborn, of the American Museum of Natural History in New York - City, first described Tyrannosaurus rex in 1905. This first specimen of - Tyrannosaurus is now on display at the Carnegie Museum of Natural History in - Pittsburgh, Pennsylvania. - |] - "", - - CalendarEntry (445 & millionYearsAgo) Nothing - "The first mass extinction" - "Fluctuating sea levels cause mass die-off of marine invertebrates" - [text| - The earliest known mass extinction, the Ordovician Extinction, took place at - a time when most of the life on Earth lived in its seas. Its major - casualties were marine invertebrates including brachiopods, trilobites, - bivalves and corals; many species from each of these groups went extinct - during this time. The cause of this extinction? It’s thought that the main - catalyst was the movement of the supercontinent Gondwana into Earth’s - southern hemisphere, which caused sea levels to rise and fall repeatedly - over a period of millions of years, eliminating habitats and species. The - onset of a late Ordovician ice age and changes in water chemistry may also - have been factors in this extinction. - |] - "https://www.amnh.org/shelf-life/six-extinctions", - - CalendarEntry (370 & millionYearsAgo) Nothing - "Late Devonian Extinction" - "The Kellwasser Event and the Hangenberg Event combine to cause an enormous loss in biodiversity" - [text| - Given that it took place over a huge span of time—estimates range from - 500,000 to 25 million years—it isn’t possible to point to a single cause for - the Devonian extinction, though some suggest that the amazing spread of - plant life on land during this time may have changed the environment in ways - that made life harder, and eventually impossible, for the species that died - out. - - The brunt of this extinction was borne by marine invertebrates. As in the - Ordovician Extinction, many species of corals, trilobites, and brachiopods - vanished. Corals in particular were so hard hit that they were nearly wiped - out, and didn’t recover until the Mesozoic Era, nearly 120 million years - later. Not all vertebrate species were spared, however; the early bony - fishes known as placoderms met their end in this extinction. - |] - "https://www.amnh.org/shelf-life/six-extinctions", - - CalendarEntry (252 & millionYearsAgo) Nothing - "The Great Dying" - "Mass extinction kills more than 95 percent of marine species and 70 percent of land-dwelling vertebrates" - [text| - So many species were wiped out by this mass extinction it took more than 10 - million years to recover from the huge blow to global biodiversity. This - extinction is thought to be the result of a gradual change in climate, - followed by a sudden catastrophe. Causes including volcanic eruptions, - asteroid impacts, and a sudden release of greenhouse gasses from the - seafloor have been proposed, but the mechanism behind the Great Dying - remains a mystery. - |] - "https://www.amnh.org/shelf-life/six-extinctions", - - CalendarEntry (201 & millionYearsAgo) Nothing - "Triassic-Jurassic Extinction" - "Death of more than a third of marine species and of most large amphibians" - [text| - This extinction occurred just a few millennia before the breakup of the - supercontinent of Pangaea. While its causes are not definitively - understood—researchers have suggested climate change, an asteroid impact, or - a spate of enormous volcanic eruptions as possible culprits—its effects are - indisputable. - - More than a third of marine species vanished, as did most large amphibians - of the time, as well as many species related to crocodiles and dinosaurs. - |] - "https://www.amnh.org/shelf-life/six-extinctions", - - CalendarEntry (66 & millionYearsAgo) Nothing - "Dinosaurs extinct" - "Mammals take over land & sea" - [text| - An asteroid more than 6 miles across strikes the Yucatan Peninsula, - triggering the fifth mass extinction in the world’s history. - - Some of the debris thrown into the atmosphere returned to Earth, the - friction turning the air into an oven and sparking forest fires as it landed - all over the world. The intensity of the heat pulse gave way to a prolonged - impact winter, the sky blotted out by soot and ash as temperatures fell. - - More than 75 percent of species known from the end of the Cretaceous period, - 66 million years ago, didn’t make it to the following Paleogene period. The - geologic break between the two is called the K-Pg boundary, and beaked birds - were the only dinosaurs to survive the disaster.|] - [text| - https://www.smithsonianmag.com/science-nature/why-birds-survived-and-dinosaurs-went-extinct-after-asteroid-hit-earth-180975801/, - https://www.amnh.org/shelf-life/six-extinctions - |], - - CalendarEntry (27.5 & millionYearsAgo) Nothing - "Apes and monkeys split" - "" - [text| - Studies of clock-like mutations in primate DNA have indicated that the split - between apes and Old World monkeys occurred between 30 million and 25 - million years ago. - |] - "https://www.nsf.gov/news/news_summ.jsp?cntn_id=127930", - - CalendarEntry (12.1 & millionYearsAgo) Nothing - "Humans and chimpanzees split" - "" - [text| - A 2016 study analyzed transitions at CpG sites in genome sequences, which - exhibit a more clocklike behavior than other substitutions, arriving at an - estimate for human and chimpanzee divergence time of 12.1 million years.[20] - |] - [text| - https://en.wikipedia.org/wiki/Chimpanzee%E2%80%93human_last_common_ancestor - |], - - CalendarEntry (4.4 & millionYearsAgo) Nothing - "Humans first walk upright" - "" - [text| - The earliest hominid with the most extensive evidence for bipedalism is the 4.4-million-year-old Ardipithecus ramidus. - |] - [text| - https://www.smithsonianmag.com/science-nature/becoming-human-the-evolution-of-walking-upright-13837658/ - |], - - CalendarEntry (300 & thousandYearsAgo) Nothing - "Modern humans evolve" - "" - [text| - Among the oldest known remains of Homo sapiens are those found at the - Omo-Kibish I archaeological site in south-western Ethiopia, dating to about - 233,000[2] to 196,000 years ago,[3] the Florisbad site in South Africa, - dating to about 259,000 years ago, and the Jebel Irhoud site in Morocco, - dated about 300,000 years ago. - |] - [text| - https://en.wikipedia.org/wiki/Early_modern_human - |], - - CalendarEntry (100 & thousandYearsAgo) Nothing - "Human migration out of Africa" - "" - [text| - Between 70,000 and 100,000 years ago, Homo sapiens began migrating from the - African continent and populating parts of Europe and Asia. They reached the - Australian continent in canoes sometime between 35,000 and 65,000 years ago. - - Map of the world showing the spread of Homo sapiens throughout the Earth - over time. - |] - [text| - https://www.khanacademy.org/humanities/world-history/world-history-beginnings/origin-humans-early-societies/a/where-did-humans-come-from - |], - - CalendarEntry (600 & millionYearsAgo) Nothing - "Multicellular life" - "" - [text| - |] - "", - - CalendarEntry (2.6 & millionYearsAgo) Nothing - "First Stone Tools" - [text| - Mode I: The Oldowan Industry - Stone flakes with sharp edges for cutting - |] - [text| - The earliest known Oldowan tools yet found date from 2.6 million years ago, - during the Lower Palaeolithic period, and have been uncovered at Gona in - Ethiopia.[16] After this date, the Oldowan Industry subsequently spread - throughout much of Africa, although archaeologists are currently unsure - which Hominan species first developed them, with some speculating that it - was Australopithecus garhi, and others believing that it was in fact Homo - habilis.[17] - - Homo habilis was the hominin who used the tools for most of the Oldowan in - Africa, but at about 1.9-1.8 million years ago Homo erectus inherited them. - The Industry flourished in southern and eastern Africa between 2.6 and 1.7 - million years ago, but was also spread out of Africa and into Eurasia by - travelling bands of H. erectus, who took it as far east as Java by 1.8 - million years ago and Northern China by 1.6 million years ago. - |] - "", - - CalendarEntry (1.8 & millionYearsAgo) Nothing - "First major transition in stone tool technology" - [text| - Mode II: The Acheulean Industry - Stone hand-axes shaped symmetrically from two sides - |] - [text| - From the Konso Formation of Ethiopia, Acheulean hand-axes are dated to about - 1.5 million years ago using radiometric dating of deposits containing - volcanic ashes.[6] Acheulean tools in South Asia have also been found to be - dated as far as 1.5 million years ago.[7] However, the earliest accepted - examples of the Acheulean currently known come from the West Turkana region - of Kenya and were first described by a French-led archaeology team.[8] These - particular Acheulean tools were recently dated through the method of - magnetostratigraphy to about 1.76 million years ago, making them the oldest - not only in Africa but the world.[9] The earliest user of Acheulean tools - was Homo ergaster, who first appeared about 1.8 million years ago. Not all - researchers use this formal name, and instead prefer to call these users - early Homo erectus.[3] - |] - "", - - CalendarEntry (160 & thousandYearsAgo) Nothing - "Second major transition in stone tool technology" - [text| - Mode III: The Levallois technique; The Mousterian Industry - Stone scrapers, knives, and projectile points - |] - [text| - Levallois is a "prepared-core" technique: one face of a stone core is fully - shaped by knapping in perparation. Then a large sharp flake is created by - cracking off the entire prepared face in one final stroke. - - The technique is first found in the Lower Palaeolithic but is most commonly - associated with the Neanderthal Mousterian industries of the Middle - Palaeolithic. In the Levant, the Levallois technique was also used by - anatomically modern humans during the Middle Stone Age. In North Africa, the - Levallois technique was used in the Middle Stone Age, most notably in the - Aterian industry to produce very small projectile points. While Levallois - cores do display some variability in their platforms, their flake production - surfaces show remarkable uniformity. As the Levallois technique is - counterintuitive, teaching the process is necessary and thus language is a - prerequisite for such technology.[2] - - The Mousterian (or Mode III) is a techno-complex (archaeological industry) - of stone tools, associated primarily with the Neanderthals in Europe, and to - a lesser extent the earliest anatomically modern humans in North Africa and - West Asia. The Mousterian largely defines the latter part of the Middle - Paleolithic, the middle of the West Eurasian Old Stone Age. It lasted - roughly from 160,000 to 40,000 BP. If its predecessor, known as Levallois or - Levallois-Mousterian, is included, the range is extended to as early as c. - 300,000–200,000 BP.[2] The main following period is the Aurignacian (c. - 43,000–28,000 BP) of Homo sapiens. - |] - "", - - CalendarEntry (115 & thousandYearsAgo) (Just $ 11.7 & thousandYearsAgo) - "The Ice Age begins" - "Glaciers cover most land on Earth, joining Asia to North America" - [text| - The Last Glacial Period (LGP), also known colloquially as the last ice age - or simply ice age,[1] occurred from the end of the Eemian to the end of the - Younger Dryas, encompassing the period c. 115,000 – c. 11,700 years ago. The - LGP is part of a larger sequence of glacial and interglacial periods known - as the Quaternary glaciation which started around 2,588,000 years ago and is - ongoing.[2] The definition of the Quaternary as beginning 2.58 million years - ago (Mya) is based on the formation of the Arctic ice cap. The Antarctic ice - sheet began to form earlier, at about 34 Mya, in the mid-Cenozoic - (Eocene–Oligocene extinction event). The term Late Cenozoic Ice Age is used - to include this early phase.[3] - |] - "https://en.wikipedia.org/wiki/Last_Glacial_Period", - - CalendarEntry (50 & thousandYearsAgo) Nothing - "Third major transition in stone tool technology" - [text| - Mode IV: The Aurignacian Industry - Long stone blades - |] - [text| - The widespread use of long blades (rather than flakes) of the Upper - Palaeolithic Mode 4 industries appeared during the Upper Palaeolithic - between 50,000 and 10,000 years ago, although blades were produced in small - quantities much earlier by Neanderthals.[20] The Aurignacian culture seems - to have been the first to rely largely on blades.[21] The use of blades - exponentially increases the efficiency of core usage compared to the - Levallois flake technique, which had a similar advantage over Acheulean - technology which was worked from cores. - |] - "https://en.wikipedia.org/wiki/Stone_tool#Mode_IV:_The_Aurignacian_Industry", - - CalendarEntry (35 & thousandYearsAgo) Nothing - "Last major transition in stone tool technology" - [text| - Mode V: The Microlithic Industries - Stone blades fastened to wood or bone handles - |] - [text| - Mode 5 stone tools involve the production of microliths, which were - used in composite tools, mainly fastened to a shaft.[22] Examples include - the Magdalenian culture. Such a technology makes much more efficient use of - available materials like flint, although required greater skill in - manufacturing the small flakes. Mounting sharp flint edges in a wood or bone - handle is the key innovation in microliths, essentially because the handle - gives the user protection against the flint and also improves leverage of - the device. - |] - "https://en.wikipedia.org/wiki/Stone_tool#Mode_V:_The_Microlithic_Industries" - , - - CalendarEntry (12 & thousandYearsAgo) Nothing - "Agriculture leads to permanent settlements" - "Neolithic age (\"new stone age\")" - [text| - Wild grains were collected and eaten from at least 105,000 years ago.[2] - However, domestication did not occur until much later. The earliest evidence - of small-scale cultivation of edible grasses is from around 21,000 BC with - the Ohalo II people on the shores of the Sea of Galilee.[3] By around 9500 - BC, the eight Neolithic founder crops – emmer wheat, einkorn wheat, hulled - barley, peas, lentils, bitter vetch, chickpeas, and flax – were cultivated - in the Levant.[4] Rye may have been cultivated earlier, but this claim - remains controversial.[5] Rice was domesticated in China by 6200 BC[6] with - earliest known cultivation from 5700 BC, followed by mung, soy and azuki - beans. Rice was also independently domesticated in West Africa and - cultivated by 1000 BC.[7][8] Pigs were domesticated in Mesopotamia around - 11,000 years ago, followed by sheep. Cattle were domesticated from the wild - aurochs in the areas of modern Turkey and India around 8500 BC. Camels were - domesticated late, perhaps around 3000 BC. - |] - "https://en.wikipedia.org/wiki/History_of_agriculture", - - CalendarEntry (6.5 & thousandYearsAgo) Nothing - "First copper tools" - "" - "" - "", - - CalendarEntry (5.3 & thousandYearsAgo) Nothing - "First bronze tools, first written language" - "The Bronze Age" - "" - "", - - CalendarEntry (3000 & yearsBeforeCommonEra) (Just $ 2350 & yearsBeforeCommonEra) - "Corded Ware culture" - "Indo-European languages spread across Europe and Asia" - [text| - The Corded Ware culture comprises a broad archaeological horizon of Europe - between ca. 3000 BCE – 2350 BCE, thus from the late Neolithic, through the - Copper Age, and ending in the early Bronze Age.[2] Corded Ware culture - encompassed a vast area, from the contact zone between the Yamnaya culture - and the Corded Ware culture in south Central Europe, to the Rhine on the - west and the Volga in the east, occupying parts of Northern Europe, Central - Europe and Eastern Europe.[2][3] The Corded Ware culture is thought to have - originated from the westward migration of Yamnaya-related people from the - steppe-forest zone into the territory of late Neolithic European cultures - such as the Globular Amphora and Funnelbeaker cultures,[4][5][6] and is - considered to be a likely vector for the spread of many of the Indo-European - languages in Europe and Asia.[1][7][8][9] - - Corded Ware encompassed most of continental northern Europe from the Rhine - on the west to the Volga in the east, including most of modern-day Germany, - the Netherlands, Denmark, Poland, Lithuania, Latvia, Estonia, Belarus, Czech - Republic, Austria, Hungary, Slovakia, Switzerland, northwestern Romania, - northern Ukraine, and the European part of Russia, as well as coastal Norway - and the southern portions of Sweden and Finland.[2] In the Late - Eneolithic/Early Bronze Age, it encompassed the territory of nearly the - entire Balkan Peninsula, where Corded Ware mixed with other steppe - elements.[11] - - Archaeologists note that Corded Ware was not a "unified culture," as Corded - Ware groups inhabiting a vast geographical area from the Rhine to Volga seem - to have regionally specific subsistence strategies and economies.[2]: 226  - There are differences in the material culture and in settlements and - society.[2] At the same time, they had several shared elements that are - characteristic of all Corded Ware groups, such as their burial practices, - pottery with "cord" decoration and unique stone-axes.[2] - |] - "", - - CalendarEntry (2800 & yearsBeforeCommonEra) (Just $ 1800 & yearsBeforeCommonEra) - "Bell Beaker culture" - [text| - copper daggers, v-perforated buttons, stone wrist-guards - copper, bronze, and gold working - long-distance exchange networks, archery - social stratification and the emergence of regional elites - |] - [text| - The Bell Beaker culture (also described as the Bell Beaker complex or Bell - Beaker phenomenon) is an archaeological culture named after the - inverted-bell beaker drinking vessel used at the very beginning of the - European Bronze Age. Arising from around 2800 BC, it lasted in Britain until - as late as 1800 BC[1][2] but in continental Europe only until 2300 BC, when - it was succeeded by the Unetice culture. The culture was widely dispersed - throughout Western Europe, being present in many regions of Iberia and - stretching eastward to the Danubian plains, and northward to the islands of - Great Britain and Ireland, and was also present in the islands of Sicily and - Sardinia and some small coastal areas in north-western Africa. The Bell - Beaker phenomenon shows substantial regional variation, and a study[3] from - 2018 found that it was associated with genetically diverse populations. - - In its mature phase, the Bell Beaker culture is understood as not only a - collection of characteristic artefact types, but a complex cultural - phenomenon involving metalwork in copper and gold, long-distance exchange - networks, archery, specific types of ornamentation, and (presumably) shared - ideological, cultural and religious ideas, as well as social stratification - and the emergence of regional elites.[6][7] A wide range of regional - diversity persists within the widespread late Beaker culture, particularly - in local burial styles (including incidences of cremation rather than - burial), housing styles, economic profile, and local ceramic wares - (Begleitkeramik). Nonetheless, according to Lemercier (2018) the mature - phase of the Beaker culture represents "the appearance of a kind of Bell - Beaker civilization of continental scale."[8] - - Bell Beaker people took advantage of transport by sea and rivers, creating a - cultural spread extending from Ireland to the Carpathian Basin and south - along the Atlantic coast and along the Rhône valley to Portugal, North - Africa, and Sicily, even penetrating northern and central Italy.[50] Its - remains have been found in what is now Portugal, Spain, France (excluding - the central massif), Ireland and Great Britain, the Low Countries and - Germany between the Elbe and Rhine, with an extension along the upper Danube - into the Vienna Basin (Austria), Hungary and the Czech Republic, with - Mediterranean outposts on Sardinia and Sicily; there is less certain - evidence for direct penetration in the east. - |] - "https://en.wikipedia.org/wiki/Bell_Beaker_culture", - - CalendarEntry (11.7 & thousandYearsAgo) Nothing - "Ice Age ends" - "" - "" - "https://en.wikipedia.org/wiki/Last_Glacial_Period", - - CalendarEntry (1600 & yearsBeforeCommonEra) Nothing - "Dynastic China" - "History begins" - [text| - The earliest known written records of the history of China date from as - early as 1250 BC, from the Shang dynasty (c. 1600–1046 BC), during the king - Wu Ding's reign - - The state-sponsored Xia–Shang–Zhou Chronology Project dated them from c. - 1600 to 1046 BC based on the carbon 14 dates of the Erligang site. - |] - "", - - CalendarEntry (480 & yearsBeforeCommonEra) Nothing - "Old Testament, Buddha" - "" - "" - "", - - CalendarEntry (6 & yearsBeforeCommonEra) Nothing - "Christ born" - "" - "" - "", - - -- CalendarEntry (300 & yearsBeforeCommonEra) Nothing - -- "Eratosthenes calculates the circumference of Earth" - -- "" - -- "" - -- "", - - CalendarEntry (theYear 570) Nothing - "Muhammad born" - "" - "" - "", - - CalendarEntry (theYear 1492) Nothing - "Columbus arrives in America" - "" - "" - "" - ] diff --git a/countdown.hs b/countdown.hs deleted file mode 100755 index 1910bec..0000000 --- a/countdown.hs +++ /dev/null @@ -1,523 +0,0 @@ -#!/usr/bin/env stack -{- stack script --resolver lts-19.23 --install-ghc -} -{-# OPTIONS_GHC - -Wall - -Wno-unused-imports - -Wno-unused-top-binds - -Wno-name-shadowing -#-} -{-# language NoImplicitPrelude #-} -{-# language RecordWildCards #-} -{-# language FlexibleContexts #-} -{-# language TemplateHaskell #-} -{-# language ViewPatterns #-} -{-# language OverloadedStrings #-} -import Rebase.Prelude hiding (toList, on, (<+>), Max) -import qualified Rebase.Prelude as Prelude -import Control.Lens hiding ((<|)) -import Data.Foldable (toList) -import Data.Ratio -import Text.Printf -import Graphics.Vty -import Data.Time.LocalTime -import Control.Monad.RWS -import Data.Time.Calendar.OrdinalDate -import qualified Data.Text as Text -import Data.Text.Format.Numbers -import Rebase.Data.Map.Strict (Map) -import qualified Rebase.Data.Map.Strict as Map - -import Brick -import Brick.Types -import Data.Text (unpack) -import Control.Lens -import Control.Monad (void, forever) -import Control.Concurrent (threadDelay, forkIO) -import qualified Graphics.Vty as V -import Brick.Widgets.ProgressBar as P -import Brick.BChan -import Brick.Widgets.Center -import Brick.Widgets.Border -import Brick.Main - ( App(..) - , showFirstCursor - , customMain - , continue - , halt - ) -import Brick.AttrMap - ( attrMap - ) -import Brick.Types - ( Widget - , Next - , EventM - , BrickEvent(..) - ) -import Brick.Widgets.Core - ( (<=>) - , str - ) -import Brick.AttrMap as A -import Brick.Util (fg, bg, on, clamp) -import Brick.Widgets.Core -import Brick.Widgets.Table - -import CosmicCalendar -import CosmicCalendarEvents - -data CustomEvent = TimeChanged ZonedTime deriving Show - -data St = - St { _stLastBrickEvent :: Maybe (BrickEvent () CustomEvent) - , _stClockTime :: LocalTime - , _stDisplayTime :: LocalTime - , _stNextEvent :: Maybe UTCTime - , _stPaused :: Bool - , _stShowConversion :: Bool - } - -makeLenses ''St - -yearNumber :: LocalTime -> Integer -yearNumber (LocalTime t _) = y - where - (y, _, _) = toGregorian t - -yearEnd :: LocalTime -> LocalTime -yearEnd (LocalTime d _) = LocalTime d' t' - where - d' = fromGregorian (y + 1) 1 1 - t' = TimeOfDay 0 0 0 - (y, _, _) = toGregorian d - - -dayNumOfYear :: LocalTime -> Int -dayNumOfYear = snd . toOrdinalDate . localDay - -pluralize :: (Num n, Eq n) => n -> String -pluralize 1 = "" -pluralize _ = "s" - -pluralizeVerb :: (Num n, Eq n) => n -> String -pluralizeVerb 1 = "s" -pluralizeVerb _ = "" - -drawUI :: St -> [Widget ()] -drawUI st = [a] - where - a = vBox [ - -- (str $ "Last event: " <> (show $ st ^. stLastBrickEvent)), - -- (str "\n"), - (str "\n"), - (countdownWidget (st ^. stShowConversion) (isSimulatedTime st) $ st ^. stDisplayTime) - ] - -showTime' :: Bool -> NominalDiffTime -> String -showTime' True 1 = printf "%-3s second" ("1" :: Text) -showTime' True t | t < 60 = printf "%.1f seconds" (realToFrac t :: Float) -showTime' _ t = showTime t - -showTime :: NominalDiffTime -> String -showTime t | t < 1 = printf "%.3f seconds" (realToFrac t :: Float) -showTime t | t == 1 = "1 second" --- showTime t | t < 10 = formatTime defaultTimeLocale "%2Es seconds" t -- BUG! Doesn't respect parameter at all! -showTime t | t < 60 = printf "%.1f seconds" (realToFrac t :: Float) -showTime t | t == 60 = formatTime defaultTimeLocale "%M minute" t -showTime t | t < 60*2 = formatTime defaultTimeLocale "%M minute %Ss" t -showTime t | t < 60*10 = formatTime defaultTimeLocale "%M minutes %Ss" t -showTime t | t < 60*60 = formatTime defaultTimeLocale "%M minutes" t -showTime t | t == 60*60 = "1 hour" -showTime t | t < 60*60*2 = formatTime defaultTimeLocale "%H hour %Mm" t -showTime t | t < 60*60*24 = formatTime defaultTimeLocale "%H hours %Mm" t -showTime t | t == 60*60*24 = formatTime defaultTimeLocale "%d day" t -showTime t | t < 60*60*24*2 = formatTime defaultTimeLocale "%d day %Hh" t -showTime t | t == 60*60*24*7 = formatTime defaultTimeLocale "%d days" t -showTime t | t < 60*60*24*10 = formatTime defaultTimeLocale "%d days %Hh" t -showTime t = formatTime defaultTimeLocale "%d days" t --- showTime _ t = formatTime defaultTimeLocale "%w weeks %D days" t - -yearsToCosmicTime :: Integral i => i -> NominalDiffTime -yearsToCosmicTime = (/ (realToFrac ageOfUniverseInYears)) . (* lengthOfYear) . realToFrac - -showCosmicYears :: Integer -> Widget n -showCosmicYears = str . showTime . yearsToCosmicTime - -toCosmicTime :: NominalDiffTime -> Rational -toCosmicTime t = realToFrac ageOfUniverseInYears * (realToFrac $ t // yearLength) :: Rational - where - yearLength = daysPerYear * nominalDay - x // y = fromRational $ toRational x / toRational y :: Double - -showCosmicTime :: NominalDiffTime -> String -showCosmicTime n = showLarge (fromRational $ toCosmicTime n) ++ " years" - -conversionTableRowFromCosmicSeconds :: NominalDiffTime -> [Widget n] -conversionTableRowFromCosmicSeconds n = [cosmicTime, realTime] - where - realTime = str $ showCosmicTime n - cosmicTime = str $ showTime n - -cosmicConversion' :: Widget n -cosmicConversion' = renderTable $ - table - [ - conversionTableRowFromCosmicSeconds $ 30 * 24 * 60 * 60, - conversionTableRowFromCosmicSeconds $ 7 * 24 * 60 * 60, - conversionTableRowFromCosmicSeconds $ 24 * 60 * 60, - conversionTableRowFromCosmicSeconds $ 60 * 60, - conversionTableRowFromCosmicSeconds $ 60, - conversionTableRowFromCosmicSeconds $ 1 - ] - -cosmicConversion :: Widget n -cosmicConversion = renderTable $ - table - [ - [str "1 billion years" , showCosmicYears $ 1000 * 1000 * 1000], - [str "100 million years" , showCosmicYears $ 100 * 1000 * 1000], - [str "10 million years" , showCosmicYears $ 10 * 1000 * 1000], - [str "1 million years" , showCosmicYears $ 1000 * 1000], - [str "100 thousand years" , showCosmicYears $ 100 * 1000], - [str "10 thousand years" , showCosmicYears $ 10 * 1000], - [str "1 thousand years" , showCosmicYears 1000], - [str "100 years" , showCosmicYears 100], - [str "10 years" , showCosmicYears 10], - [str "1 year" , showCosmicYears 1] - ] - -showLarge :: Double -> String -showLarge n | n >= 10 * 1000 * 1000 * 1000 = printf "%.0f billion" (n / (1000 * 1000 * 1000)) -showLarge n | n >= 1000 * 1000 * 1000 = printf "%.1f billion" (n / (1000 * 1000 * 1000)) -showLarge n | n >= 10 * 1000 * 1000 = printf "%.0f million" (n / (1000 * 1000)) -showLarge n | n >= 1000 * 1000 = printf "%.1f million" (n / (1000 * 1000)) -showLarge n | n >= 10 * 1000 = printf "%.0f thousand" (n / 1000) -showLarge n | n >= 10 = unpack $ commasF 0 n -showLarge n = printf "%.3f" n - -countdownWidget :: Bool -> Bool -> LocalTime -> Widget n -countdownWidget showConversion isSimulated t = - (border $ vBox [ - (hCenter $ hBox - [ countdownBox - , currentTimeBox - , cosmicTimeBox - ]) - , - str "\n" - , - (borderWithLabel (str progressLabel) $ - updateAttrMap - (A.mapAttrName yDoneAttr P.progressCompleteAttr . - A.mapAttrName yToDoAttr P.progressIncompleteAttr) $ - progressBar Nothing (realToFrac $ yearElapsed // yearLength)) - ]) - <=> - str "\n" - <=> - hCenter (hBox [ - -- TODO: accumulate all entries on today's date into one vBox - if currentEntryIsCurrent then - (borderWithLabel (txt "Now on the Cosmic Calendar") currentEntry) <=> - (fromMaybe (str "") $ fmap (borderWithLabel (txt "Next on the Cosmic Calendar")) nextEntryShort) - else - borderWithLabel (txt "Next on the Cosmic Calendar") nextEntry, - -- vBox [ cosmicCalendarCurrent, txt "\n", cosmicCalendarNext ], - if showConversion - then - str " " <=> borderWithLabel (str "Cosmic Conversion") (hBox [cosmicConversion, cosmicConversion']) - else - str "" - ]) - where - -- TODO: We want to display "today" or "now" on the cosmic calendar; - -- We want to display what happened previously on the cosmic calendar - -- We want to say how long ago the previous happening was relative to today's date and today's place on the cosmic calendar - -- (E.g., if it's 1AM Jan 1, then we say the big bang was 1 hour ago and 1.6 million years ago) - -- We want to say similar for how long until the next happening - -- We also _may_ want to say the same thing for the current happening, depending on if it's an instant or a stage - -- If it's a stage, we want to say how long it lasts; how long since it started, and how long until it ends - - currentEntryIsCurrent = fromMaybe True $ do - (LocalTime entryDay _) <- (`addLocalTime` yearStart t) . calBeginTime <$> getCurrentCalendarEntry theCalendar t - let (LocalTime nowDay _) = t - return $ entryDay == nowDay - currentEntry = fromMaybe (str "none") $ calendarWidget False <$> getCurrentCalendarEntry theCalendar t - nextEntry = fromMaybe (str "none") $ calendarWidget False <$> getNextCalendarEntry theCalendar t - nextEntryShort = fmap (str "\n" <=>) (calendarWidget True <$> getNextCalendarEntry theCalendar t) - - calendarWidget short CalendarEntry{..} = box -- vBox [eventCountdown, str "\n", box] - where - timeUntilActive = (calBeginTime `addLocalTime` yearStart t) `diffLocalTime` t - eventCountdown = if timeUntilActive >= 0 then - hBox [str $ "in " ++ showTime timeUntilActive, - padLeft Max $ str $ "in " ++ showCosmicTime timeUntilActive] - else - hBox [str $ showTime (-timeUntilActive) ++ " ago", - padLeft Max $ str $ showCosmicTime (-timeUntilActive) ++ " ago"] - years = fromRational $ toCosmicTime calBeginTime - box = vBox [ - if currentEntryIsCurrent && not short - then str "\n" - else eventCountdown <=> str "\n", - hCenter $ txt calTitle, - hCenter $ txt calSubtitle, - str "\n", - hBox [ - let cosmicSecondsAgo = nominalDiffTimeToSeconds (yearEnd cosmicCalendarT `diffLocalTime` cosmicCalendarT) - cosmicCalendarT = calBeginTime `addLocalTime` yearStart t - in vBox [ - str $ formatTime defaultTimeLocale "%A, %B %e%n%Y-%m-%d %r" $ cosmicCalendarT, - -- TODO: Choose correct cosmic unit - str $ printf "%s cosmic second%s ago" (commasF' 1 cosmicSecondsAgo) (pluralize cosmicSecondsAgo) - ], - padLeft Max $ vBox [ - str $ showLarge years ++ " years", - str $ printf "%s years ago" $ showLarge $ realToFrac (ageOfUniverseInYears - floor years) - ] - ], - -- str $ printf "%s years ago" (commas $ ageOfUniverseInYears - floor years), - if not short - then - str "\n" <=> - txtWrap calDescription - else - str "" - ] - - strWhen b s = str $ if b then s else "" - countdownBox = - (borderWithLabel (str $ printf "Countdown %d" currentYear) $ - vBox $ - let secondsNow = 1 + toSeconds yearElapsed :: Int - secondsTotal = toSeconds yearLength - in - (str $ printf "Day %d of %d\nSecond %s of %s\n%s seconds remain" - dayNum - numDays - (commas secondsNow) - (commas secondsTotal) - (commas $ secondsTotal - secondsNow) - ) : remains - ) - remains = - [ - strWhen (hoursLeft >= 24) $ - printf "%d day%s remain%s" - daysLeft - (pluralize daysLeft) - (pluralizeVerb daysLeft), - - strWhen (hoursLeft < 24 && hoursLeft > 1) $ - printf "%s hour%s remain%s" - (commasF 2 hoursLeft) - (pluralize $ (floor hoursLeft :: Integer)) - (pluralizeVerb $ (floor hoursLeft :: Integer)), - - strWhen (hoursLeft <= 1 && minutesLeft > 1) $ - printf "%s minute%s remain%s" - (commasF 2 minutesLeft) - (pluralize $ (floor minutesLeft :: Integer)) - (pluralizeVerb $ (floor minutesLeft :: Integer)), - - strWhen (minutesLeft <= 1) $ - printf "%s second%s remain%s" - (commasF' 1 secondsLeft) - (pluralize secondsLeft) - (pluralizeVerb secondsLeft) - ] - - cosmicTimeBox = - (borderWithLabel (str "Cosmic Time") $ - vBox [(str $ printf "%s years" (commas $ (floor cosmicYears :: Integer))), - str "\n", - (str $ printf "%s years ago" (commas $ (floor cosmicYearsAgo :: Integer))) - -- , (str $ printf "%s years ago" (showLarge $ (realToFrac cosmicYearsAgo))) - -- , (str $ printf "%s billion years ago" (commasF 9 $ cosmicYearsAgo / (1000*1000*1000))) - -- , (str $ printf "%s million years ago" (commasF 6 $ cosmicYearsAgo / (1000*1000))) - -- , (str $ printf "%s thousand years ago" (commasF 3 $ cosmicYearsAgo / 1000)) - -- , (str $ printf "%s days ago" (commas $ (floor $ realToFrac cosmicYearsAgo * daysPerYear :: Integer))) - ]) - currentTimeBox = (hCenter (borderWithLabel (str $ printf "Current time%s" (if isSimulated then " (SIMULATED)" else "" :: String)) $ - padLeftRight 3 $ (str (formatTime defaultTimeLocale "%A, %B %e%n%Y-%m-%d %r" t)))) - cosmicYears = realToFrac ageOfUniverseInYears * (realToFrac $ (yearElapsed // yearLength)) :: Rational - cosmicYearsAgo = realToFrac ageOfUniverseInYears * (realToFrac $ 1 - (yearElapsed // yearLength)) :: Rational - -- cosmicYearsAgo = if yearElapsed == yearLength - -- then 0 - -- else realToFrac ageOfUniverseInYears * (realToFrac $ 1 - (yearElapsed // yearLength)) :: Rational - currentYear = yearNumber t - dayNum = dayNumOfYear t - numDays = daysInYear t - -- yearLength = fromIntegral numDays * nominalDay - yearLength = yearEnd t `diffLocalTime` yearStart t - yearElapsed = t `diffLocalTime` yearStart t - - daysLeft = numDays - dayNum - hoursLeft = minutesLeft / 60 - minutesLeft = fromRational $ toRational secondsLeft / 60 :: Double - toSeconds = floor . nominalDiffTimeToSeconds - secondsLeft = nominalDiffTimeToSeconds (yearLength - yearElapsed) - x // y = fromRational $ toRational x / toRational y :: Double - progressLabel = printf "%.6F%%" (100 * (yearElapsed // yearLength)) - -commasF' 1 n = if (floor (n * 10) `mod` 10 :: Int) == 0 then commasF 0 n `Text.append` " " else commasF 1 n -commasF' p n = commasF p n - -commasF', commasF :: RealFrac x => Int -> x -> Text -commasF precision = prettyF cfg - where - cfg = PrettyCfg precision (Just ',') '.' - -commas :: Integral i => i -> Text -commas = prettyI (Just ',') . fromIntegral - -nextTenthOfSecond :: ZonedTime -> ZonedTime -nextTenthOfSecond (ZonedTime (LocalTime day (TimeOfDay h m s)) z) = (ZonedTime (LocalTime day (TimeOfDay h m s')) z) - where - s' = fromRational $ toRational (floor (s * 10) + 1 :: Integer) / 10 - -nextWholeSecond :: ZonedTime -> ZonedTime -nextWholeSecond (ZonedTime (LocalTime day (TimeOfDay h m s)) z) = (ZonedTime (LocalTime day (TimeOfDay h m s')) z) - where - s' = fromIntegral $ (floor s + 1 :: Int) - -diffZonedTime :: ZonedTime -> ZonedTime -> NominalDiffTime -diffZonedTime = diffLocalTime `Prelude.on` zonedTimeToLocalTime - -isNewYearsEve :: LocalTime -> Bool -isNewYearsEve t = dayNumOfYear t == daysInYear t - -queueNextEvent :: MonadIO m => Bool -> BChan CustomEvent -> m ZonedTime -queueNextEvent hyper chan = liftIO $ do - now <- getZonedTime - void . forkIO $ do - - let getNext = if hyper then nextTenthOfSecond else nextWholeSecond - next = getNext now - delay = next `diffZonedTime` now - threadDelay $ floor $ delay * 1000 * 1000 - writeBChan chan $ TimeChanged next - return now - -isSimulatedTime :: St -> Bool -isSimulatedTime st = st ^. stDisplayTime /= st ^. stClockTime - -nextCalendarEntryTime :: LocalTime -> LocalTime -nextCalendarEntryTime t = fromMaybe t $ getNextCalendarEntry theCalendar t <&> (`addLocalTime` yearStart t) . calBeginTime - -previousCalendarEntryTime :: LocalTime -> LocalTime -previousCalendarEntryTime t = fromMaybe t $ goBack t - where - goBack t = getPreviousCalendarEntry theCalendar t <&> (`addLocalTime` yearStart t) . calBeginTime - -handleEvent :: BChan CustomEvent -> St -> BrickEvent () CustomEvent -> EventM () (Next St) -handleEvent chan st e = - case e of - VtyEvent (V.EvKey V.KEsc []) -> halt st - VtyEvent (V.EvKey (V.KChar 'p') []) -> cont $ st & stPaused %~ not - VtyEvent (V.EvKey (V.KFun 1) []) -> cont $ st & stPaused %~ not - - VtyEvent (V.EvKey V.KRight [MShift]) -> cont $ st & stDisplayTime %~ (addLocalTime (1)) - VtyEvent (V.EvKey V.KLeft [MShift]) -> cont $ st & stDisplayTime %~ (addLocalTime (-1)) - - VtyEvent (V.EvKey V.KRight [MCtrl]) -> cont $ st & stDisplayTime %~ (addLocalTime (60)) - VtyEvent (V.EvKey V.KLeft [MCtrl]) -> cont $ st & stDisplayTime %~ (addLocalTime (-60)) - - VtyEvent (V.EvKey V.KPageDown [MCtrl]) -> cont $ st & stDisplayTime %~ (addLocalTime (60 * 60)) - VtyEvent (V.EvKey V.KPageUp [MCtrl]) -> cont $ st & stDisplayTime %~ (addLocalTime (-60 * 60)) - VtyEvent (V.EvKey V.KPageDown []) -> cont $ st & stDisplayTime %~ (addLocalTime lengthOfDay) - VtyEvent (V.EvKey V.KPageUp []) -> cont $ st & stDisplayTime %~ (addLocalTime (-lengthOfDay)) - - VtyEvent (V.EvKey V.KHome []) -> cont $ st & stDisplayTime .~ (st ^. stClockTime) - VtyEvent (V.EvKey V.KHome [MShift]) -> cont $ st & stDisplayTime .~ (yearStart $ st ^. stClockTime) - VtyEvent (V.EvKey V.KEnd []) -> cont $ st & stDisplayTime .~ (newYearsEveLast10 $ st ^. stClockTime) - VtyEvent (V.EvKey V.KEnd [MShift]) -> cont $ st & stDisplayTime .~ (yearEnd $ st ^. stClockTime) - VtyEvent (V.EvKey V.KEnd [MCtrl]) -> cont $ st & stDisplayTime .~ (newYearsEveNoon $ st ^. stClockTime) - - VtyEvent (V.EvKey V.KRight []) -> cont $ st & stDisplayTime %~ nextCalendarEntryTime - VtyEvent (V.EvKey V.KLeft []) -> cont $ st & stDisplayTime %~ previousCalendarEntryTime - VtyEvent (V.EvKey (V.KChar '.') []) -> cont $ st & stDisplayTime %~ nextCalendarEntryTime - VtyEvent (V.EvKey (V.KChar ',') []) -> cont $ st & stDisplayTime %~ previousCalendarEntryTime - - VtyEvent (V.EvKey (V.KChar 'c') []) -> cont $ st & stShowConversion %~ not - VtyEvent (V.EvKey (V.KFun 2) []) -> cont $ st & stShowConversion %~ not - - VtyEvent _ -> cont st - AppEvent (TimeChanged now) -> do - let hyper = isNewYearsEve $ st ^. stDisplayTime - void $ queueNextEvent hyper chan - let oldTime = st ^. stClockTime - cont $ st & stClockTime .~ (zonedTimeToLocalTime now) - & stDisplayTime %~ if st ^. stPaused then id else addLocalTime $ zonedTimeToLocalTime now `diffLocalTime` oldTime - _ -> cont st - where - cont s = do - continue $ s & stLastBrickEvent .~ (Just e) - -newYearsEveLast10 :: LocalTime -> LocalTime -newYearsEveLast10 = addLocalTime (-11) . yearEnd - -newYearsEveNoon :: LocalTime -> LocalTime -newYearsEveNoon (LocalTime d (TimeOfDay _ _ s)) = LocalTime d' t - where - (y, _) = toOrdinalDate d - d' = fromOrdinalDate y 366 - t = TimeOfDay 12 0 s' - s' = s `mod'` 1 -- keep the fractional part so we still tick the display on the same schedule - -initialState :: LocalTime -> St -initialState t = - St { _stLastBrickEvent = Nothing - , _stClockTime = t - , _stDisplayTime = t - , _stNextEvent = Nothing - , _stPaused = False - , _stShowConversion = False - } - -daysInYear :: LocalTime -> Int -daysInYear (toGregorian . localDay -> (y, _, _)) = if isLeapYear y then 366 else 365 - -theBaseAttr :: A.AttrName -theBaseAttr = A.attrName "theBase" - -xDoneAttr, xToDoAttr :: A.AttrName -xDoneAttr = theBaseAttr <> A.attrName "X:done" -xToDoAttr = theBaseAttr <> A.attrName "X:remaining" - -yDoneAttr, yToDoAttr :: A.AttrName -yDoneAttr = theBaseAttr <> A.attrName "Y:done" -yToDoAttr = theBaseAttr <> A.attrName "Y:remaining" - -zDoneAttr, zToDoAttr :: A.AttrName -zDoneAttr = theBaseAttr <> A.attrName "Z:done" -zToDoAttr = theBaseAttr <> A.attrName "Z:remaining" - -theMap :: A.AttrMap -theMap = A.attrMap V.defAttr - [ (theBaseAttr, bg V.brightBlack) - , (xDoneAttr, V.black `on` V.white) - , (xToDoAttr, V.white `on` V.black) - , (yDoneAttr, V.magenta `on` V.yellow) - , (zDoneAttr, V.blue `on` V.green) - , (zToDoAttr, V.blue `on` V.red) - , (P.progressIncompleteAttr, fg V.yellow) - ] - -theApp :: BChan CustomEvent -> App St CustomEvent () -theApp chan = - App { appDraw = drawUI - , appChooseCursor = showFirstCursor - , appHandleEvent = handleEvent chan - , appStartEvent = return - , appAttrMap = const theMap - } - -main :: IO () -main = do - chan <- newBChan 10 - - let buildVty = V.mkVty V.defaultConfig - initialVty <- buildVty - now <- queueNextEvent False chan - void $ customMain initialVty buildVty (Just chan) (theApp chan) (initialState $ zonedTimeToLocalTime now) diff --git a/package.yaml b/package.yaml index 0791194..975e9f2 100644 --- a/package.yaml +++ b/package.yaml @@ -17,6 +17,7 @@ dependencies: executables: countdown: + source-dirs: src main: countdown.hs other-modules: CosmicCalendar, CosmicCalendarEvents ghc-options: diff --git a/src/CosmicCalendar.hs b/src/CosmicCalendar.hs new file mode 100644 index 0000000..db29c02 --- /dev/null +++ b/src/CosmicCalendar.hs @@ -0,0 +1,140 @@ +{-# OPTIONS_GHC + -Wall + -Wno-unused-imports + -Wno-unused-top-binds + -Wno-name-shadowing +#-} +{-# language NoImplicitPrelude #-} +{-# language RecordWildCards #-} +{-# language FlexibleContexts #-} +{-# language TemplateHaskell #-} +{-# language ViewPatterns #-} +{-# language OverloadedStrings #-} +{-# language QuasiQuotes #-} + +module CosmicCalendar where + +import Rebase.Prelude +import qualified Rebase.Prelude as Prelude +import Control.Lens hiding ((<|)) +import Data.Foldable (toList) +import Data.Ratio +import Text.Printf +import Data.Time.Calendar.OrdinalDate +import Data.Time.LocalTime +import Control.Monad.RWS +import Data.Time.Calendar.OrdinalDate +import Data.Text.Format.Numbers +import NeatInterpolation +import qualified Data.Text as Text +import Data.Text (Text, pack, unpack) + +import Rebase.Data.Map.Strict (Map) +import qualified Rebase.Data.Map.Strict as Map + +-- 13.787±0.020 billion years. Source: https://en.wikipedia.org/wiki/Age_of_the_universe#cite_note-Planck_2018-2 +ageOfUniverseInYears :: Integer +ageOfUniverseInYears = 13787 * 1000 * 1000 + +-- The point of the cosmic calendar is to mentally visualize or model the scale +-- of cosmic/geologic/evolutionary events using the existing internal mental +-- model of the year. This internal mental model of the year is NOT a 365.2422 +-- day earth rotation, but a 365 day calendar year. +-- +-- In order to make the math of the calendar work out, the functions that look +-- up calendary entries (and take as input the LocalTime) must check for leap +-- year, and subtract one day from the input if it is later than February. +daysPerYear :: NominalDiffTime +daysPerYear = 365 -- NOT 365.2422 + +lengthOfDay :: NominalDiffTime +lengthOfDay = 24 * 60 * 60 + +lengthOfYear :: NominalDiffTime +lengthOfYear = daysPerYear * lengthOfDay + +ageOfUniverse :: NominalDiffTime +ageOfUniverse = fromIntegral ageOfUniverseInYears * lengthOfYear + +data CalendarEntry = CalendarEntry { + calBeginTime :: NominalDiffTime, + calEndTime :: Maybe NominalDiffTime, + calTitle :: Text, + calSubtitle :: Text, + calDescription :: Text, + calReferences :: Text +} deriving (Show) + +-- TODO: Encode the input times like so: +-- +-- data CosmicTime = YearsAgo Rational | YearsAfterBigBang Rational | YearsBCE Rational | YearsCE Rational +-- +-- The absolute time values (YearsBCE and YearsCE) will be computed using the +-- year at program start: + +currentYear :: Integer +currentYear = unsafePerformIO $ getZonedTime <&> toGregorian . localDay . zonedTimeToLocalTime <&> view _1 + +years :: Rational -> NominalDiffTime +years = (* lengthOfYear) . fromRational + +yearsAgo :: Rational -> NominalDiffTime +yearsAgo (fromRational -> n) = lengthOfYear * (1 - (n / fromIntegral ageOfUniverseInYears)) + +afterBigBang :: NominalDiffTime -> NominalDiffTime +afterBigBang = (/ ageOfUniverse) . (* lengthOfYear) + +thousandYears :: Rational -> NominalDiffTime +thousandYears = years . (* 1000) + +millionYears :: Rational -> NominalDiffTime +millionYears = thousandYearsAgo . (* 1000) + +billionYears :: Rational -> NominalDiffTime +billionYears = millionYearsAgo . (* 1000) + +thousandYearsAgo :: Rational -> NominalDiffTime +thousandYearsAgo = yearsAgo . (* 1000) + +millionYearsAgo :: Rational -> NominalDiffTime +millionYearsAgo = thousandYearsAgo . (* 1000) + +billionYearsAgo :: Rational -> NominalDiffTime +billionYearsAgo = millionYearsAgo . (* 1000) + +yearStart :: LocalTime -> LocalTime +yearStart (LocalTime d _) = LocalTime d' t' + where + d' = fromGregorian y 1 1 + t' = TimeOfDay 0 0 0 + (y, _, _) = toGregorian d + +localTimeToYearElapsed :: LocalTime -> NominalDiffTime +localTimeToYearElapsed t = t `diffLocalTime` yearStart t + +getPreviousCalendarEntry :: Calendar -> LocalTime -> Maybe CalendarEntry +getPreviousCalendarEntry cal (localTimeToYearElapsed -> t) = snd <$> Map.lookupLT t cal + +getCurrentCalendarEntry :: Calendar -> LocalTime -> Maybe CalendarEntry +getCurrentCalendarEntry cal (localTimeToYearElapsed -> t) = snd <$> Map.lookupLE t cal + +type Calendar = Map NominalDiffTime CalendarEntry + +getNextCalendarEntry :: Calendar -> LocalTime -> Maybe CalendarEntry +getNextCalendarEntry cal (localTimeToYearElapsed -> t) = snd <$> Map.lookupGT t cal + +buildCalendar :: [CalendarEntry] -> Map NominalDiffTime CalendarEntry +buildCalendar ls = Map.fromList $ map (\x -> (calBeginTime x, x)) $ map unwrap ls + +unwrap :: CalendarEntry -> CalendarEntry +unwrap x@CalendarEntry{..} = x { calDescription = unwrapText calDescription } + where + unwrapText :: Text -> Text + unwrapText = pack . unlines . map unwords . foldr process [] . lines . unpack + process line [] = [[line]] + process line ((x:xs):ys) | shouldMerge line x = (line:x:xs):ys + process line rest = [line]:rest + shouldMerge :: String -> String -> Bool + shouldMerge "" _ = False + shouldMerge _ "" = False + shouldMerge _ _ = True diff --git a/src/CosmicCalendarEvents.hs b/src/CosmicCalendarEvents.hs new file mode 100644 index 0000000..90b5848 --- /dev/null +++ b/src/CosmicCalendarEvents.hs @@ -0,0 +1,1012 @@ +{-# OPTIONS_GHC -Wall #-} +{-# language NoImplicitPrelude #-} +{-# language OverloadedStrings #-} +{-# language QuasiQuotes #-} + +module CosmicCalendarEvents where + +import Rebase.Prelude +import NeatInterpolation + +import CosmicCalendar + +theYear, yearsBeforeCommonEra :: Integer -> NominalDiffTime +theYear = yearsAgo . toRational . (currentYear -) +yearsBeforeCommonEra = yearsAgo . toRational . ((+) (currentYear - 1)) + +theCalendar :: Map NominalDiffTime CalendarEntry +theCalendar = buildCalendar $ + [ + CalendarEntry 0 + Nothing + "The Big Bang" + "The universe begins" + "" + "", + + CalendarEntry (370 & thousandYears & afterBigBang) + Nothing + "Recombination" + "The universe becomes transparent" + [text| + At about 370,000 years,[3][4][5][6] neutral hydrogen atoms finish forming + ("recombination"), and as a result the universe also became transparent for + the first time. The newly formed atoms—mainly hydrogen and helium with + traces of lithium—quickly reach their lowest energy state (ground state) by + releasing photons ("photon decoupling"), and these photons can still be + detected today as the cosmic microwave background (CMB). This is the oldest + direct observation we currently have of the universe. + |] + [text| + https://en.wikipedia.org/wiki/Chronology_of_the_universe#The_very_early_universe + + 3. Tanabashi, M. 2018, p. 358, chpt. 21.4.1: "Big-Bang Cosmology" (Revised + September 2017) by Keith A. Olive and John A. Peacock. + + 4. Notes: Edward L. Wright's Javascript Cosmology Calculator (last modified + 23 July 2018). With a default H 0 {\displaystyle H_{0}} H_{0} = 69.6 (based + on WMAP9+SPT+ACT+6dFGS+BOSS/DR11+H0/Riess) parameters, the calculated age of + the universe with a redshift of z = 1100 is in agreement with Olive and + Peacock (about 370,000 years). + + 5. Hinshaw, Weiland & Hill 2009. See PDF: page 45, Table 7, Age at + decoupling, last column. Based on WMAP+BAO+SN parameters, the age of + decoupling occurred 376971+3162−3167 years after the Big Bang. + + 6. Ryden 2006, pp. 194–195. "Without going into the details of the + non-equilibrium physics, let's content ourselves by saying, in round + numbers, zdec ≈ 1100, corresponding to a temperature Tdec ≈ 3000 K, when the + age of the universe was tdec ≈ 350,000 yr in the Benchmark Model. (...) The + relevant times of various events around the time of recombination are shown + in Table 9.1. (...) Note that all these times are approximate, and are + dependent on the cosmological model you choose. (I have chosen the Benchmark + Model in calculating these numbers.)" + + https://en.wikipedia.org/wiki/Recombination_(cosmology)#cite_note-2 + |], + + CalendarEntry (13.4 & billionYearsAgo) Nothing + "The first observed star" + "" + "First Light Viewed Through the Rich Cluster Abell 2218" + "https://sites.astro.caltech.edu/~rse/firstlight/", + + CalendarEntry (4.6 & billionYearsAgo) Nothing + "Formation of the Sun" + "The formation of the solar system begins" + [text| + The formation of the Solar System began about 4.6 billion years ago with the + gravitational collapse of a small part of a giant molecular cloud.[1] Most + of the collapsing mass collected in the center, forming the Sun, while the + rest flattened into a protoplanetary disk out of which the planets, moons, + asteroids, and other small Solar System bodies formed. + |] + "https://en.wikipedia.org/wiki/Formation_and_evolution_of_the_Solar_System", + + CalendarEntry (4.54 & billionYearsAgo) Nothing + "Formation of Earth" + "" + [text| + The standard model for the formation of the Solar System (including the + Earth) is the solar nebula hypothesis.[23] In this model, the Solar System + formed from a large, rotating cloud of interstellar dust and gas called the + solar nebula. It was composed of hydrogen and helium created shortly after + the Big Bang 13.8 Ga (billion years ago) and heavier elements ejected by + supernovae. About 4.5 Ga, the nebula began a contraction that may have been + triggered by the shock wave from a nearby supernova.[24] A shock wave would + have also made the nebula rotate. As the cloud began to accelerate, its + angular momentum, gravity, and inertia flattened it into a protoplanetary + disk perpendicular to its axis of rotation. Small perturbations due to + collisions and the angular momentum of other large debris created the means + by which kilometer-sized protoplanets began to form, orbiting the nebular + center.[25] + + The center of the nebula, not having much angular momentum, collapsed + rapidly, the compression heating it until nuclear fusion of hydrogen into + helium began. After more contraction, a T Tauri star ignited and evolved + into the Sun. Meanwhile, in the outer part of the nebula gravity caused + matter to condense around density perturbations and dust particles, and the + rest of the protoplanetary disk began separating into rings. In a process + known as runaway accretion, successively larger fragments of dust and debris + clumped together to form planets.[25] Earth formed in this manner about 4.54 + billion years ago (with an uncertainty of 1%)[26][27][4] and was largely + completed within 10–20 million years.[28] The solar wind of the newly formed + T Tauri star cleared out most of the material in the disk that had not + already condensed into larger bodies. The same process is expected to + produce accretion disks around virtually all newly forming stars in the + universe, some of which yield planets.[29] + |] + "https://en.wikipedia.org/wiki/History_of_Earth#Solar_System_formation", + + CalendarEntry (8.8 & billionYearsAgo) Nothing + "Thin disk of the Milky Way Galaxy" + "Our galaxy begins to form" + [text| + The age of stars in the galactic thin disk has also been estimated using + nucleocosmochronology. Measurements of thin disk stars yield an estimate + that the thin disk formed 8.8 ± 1.7 billion years ago. These measurements + suggest there was a hiatus of almost 5 billion years between the formation + of the galactic halo and the thin disk.[253] Recent analysis of the chemical + signatures of thousands of stars suggests that stellar formation might have + dropped by an order of magnitude at the time of disk formation, 10 to 8 + billion years ago, when interstellar gas was too hot to form new stars at + the same rate as before.[254] + |] + "", + + CalendarEntry (4.4 & billionYearsAgo) Nothing + "Formation of the moon" + "A collision of the planet Theia with Earth creates the moon" + [text| + Astronomers think the collision between Earth and Theia happened at about + 4.4 to 4.45 bya; about 0.1 billion years after the Solar System began to + form.[15][16] In astronomical terms, the impact would have been of moderate + velocity. Theia is thought to have struck Earth at an oblique angle when + Earth was nearly fully formed. Computer simulations of this "late-impact" + scenario suggest an initial impactor velocity at infinity below 4 kilometres + per second (2.5 mi/s), increasing as it fell to over 9.3 km/s (5.8 mi/s) at + impact, and an impact angle of about 45°.[17] However, oxygen isotope + abundance in lunar rock suggests "vigorous mixing" of Theia and Earth, + indicating a steep impact angle.[3][18] Theia's iron core would have sunk + into the young Earth's core, and most of Theia's mantle accreted onto + Earth's mantle. However, a significant portion of the mantle material from + both Theia and Earth would have been ejected into orbit around Earth (if + ejected with velocities between orbital velocity and escape velocity) or + into individual orbits around the Sun (if ejected at higher velocities). + Modelling[19] has hypothesised that material in orbit around Earth may have + accreted to form the Moon in three consecutive phases; accreting first from + the bodies initially present outside Earth's Roche limit, which acted to + confine the inner disk material within the Roche limit. The inner disk + slowly and viscously spread back out to Earth's Roche limit, pushing along + outer bodies via resonant interactions. After several tens of years, the + disk spread beyond the Roche limit, and started producing new objects that + continued the growth of the Moon, until the inner disk was depleted in mass + after several hundreds of years. + |] + [text| + https://en.wikipedia.org/wiki/Giant-impact_hypothesis#Basic_model + https://www.psi.edu/epo/moon/moon.html + |], + + CalendarEntry (3.77 & billionYearsAgo) Nothing + "Life on Earth" + "" + [text| + The earliest time for the origin of life on Earth is at least 3.77 billion + years ago, possibly as early as 4.28 billion years,[2] or even 4.41 billion + years[4][5]—not long after the oceans formed 4.5 billion years ago, and + after the formation of the Earth 4.54 billion years ago.[2][3][6][7] + |] + "https://en.wikipedia.org/wiki/Earliest_known_life_forms", + + CalendarEntry (3.42 & billionYearsAgo) Nothing + "Earliest known life on Earth" + "The fossil record begins" + [text| + The earliest known life forms on Earth are putative fossilized + microorganisms found in hydrothermal vent precipitates, considered to be + about 3.42 billion years old.[1][2] The earliest time for the origin of life + on Earth is at least 3.77 billion years ago, possibly as early as 4.28 + billion years,[2] or even 4.41 billion years[4][5]—not long after the oceans + formed 4.5 billion years ago, and after the formation of the Earth 4.54 + billion years ago.[2][3][6][7] The earliest direct evidence of life on Earth + is from microfossils of microorganisms permineralized in + 3.465-billion-year-old Australian Apex chert rocks.[8][9] + |] + "https://en.wikipedia.org/wiki/Earliest_known_life_forms", + + CalendarEntry (3.4 & billionYearsAgo) Nothing + "First photosynthetic bacteria" + "(Still no Oxygen)" + [text| + They absorbed near-infrared rather than visible light and produced sulfur or + sulfate compounds rather than oxygen. Their pigments (possibly + bacteriochlorophylls) were predecessors to chlorophyll. + |] + "https://www.scientificamerican.com/article/timeline-of-photosynthesis-on-earth/", + + CalendarEntry (2.7 & billionYearsAgo) Nothing + "Oxygen from photosynthesis" + [text| + Cyanobacteria (blue-green algae) initiates "rusting of the Earth" + The resulting Ozone layer will make life possible on land + |] + [text| + These ubiquitous bacteria were the first oxygen producers. They absorb + visible light using a mix of pigments: phycobilins, carotenoids and several + forms of chlorophyll. + + The Great Oxidation Event (GOE), also called the Great Oxygenation Event, + the Oxygen Catastrophe, the Oxygen Revolution, and the Oxygen Crisis, was a + time interval when the Earth's atmosphere and the shallow ocean first + experienced a rise in the amount of oxygen. This occurred approximately + 2.4–2.0 Ga (billion years) ago, during the Paleoproterozoic era.[2] + Geological, isotopic, and chemical evidence suggests that + biologically-produced molecular oxygen (dioxygen, O2) started to accumulate + in Earth's atmosphere and changed it from a weakly reducing atmosphere + practically free of oxygen into an oxidizing atmosphere containing abundant + oxygen.[3] + + The sudden injection of toxic oxygen into an anaerobic biosphere caused the + extinction of many existing anaerobic species on Earth.[4] Although the event is + inferred to have constituted a mass extinction,[5] due in part to the great + difficulty in surveying microscopic species' abundances, and in part to the + extreme age of fossil remains from that time, the Oxygen Catastrophe is + typically not counted among conventional lists of "great extinctions", which are + implicitly limited to the Phanerozoic eon. + + The event is inferred to have been caused by cyanobacteria producing the + oxygen, which may have enabled the subsequent development of multicellular + life-forms.[6] + + The current scientific understanding of when and how the Earth's atmosphere + changed from a weakly reducing to a strongly oxidizing atmosphere largely + began with the work of the American geologist Preston Cloud in the 1970s.[9] + Cloud observed that detrital sediments older than about 2 billion years ago + contained grains of pyrite, uraninite,[9] and siderite,[12] all minerals + containing reduced forms of iron or uranium that are not found in younger + sediments because they are rapidly oxidized in an oxidizing atmosphere. He + further observed that continental redbeds, which get their color from the + oxidized (ferric) mineral hematite, began to appear in the geological record + at about this time. Banded iron formation largely disappears from the + geological record at 1.85 billion years ago, after peaking at about 2.5 + billion years ago.[14] Banded iron formation can form only when abundant + dissolved ferrous iron is transported into depositional basins, and an + oxygenated ocean blocks such transport by oxidizing the iron to form + insoluble ferric iron compounds.[15] The end of the deposition of banded + iron formation at 1.85 billion years ago is therefore interpreted as marking + the oxygenation of the deep ocean.[9] Heinrich Holland further elaborated + these ideas through the 1980s, placing the main time interval of oxygenation + between 2.2 and 1.9 billion years ago, and they continue to shape the + current scientific understanding.[10] + |] + [text| + https://www.scientificamerican.com/article/timeline-of-photosynthesis-on-earth/ + https://en.wikipedia.org/wiki/Great_Oxidation_Event + |], + + CalendarEntry (2.05 & billionYearsAgo) Nothing + "Eukaryotic cells" + "Cells with nucleus (inner membrane holding DNA)" + [text| + Eukaryotes (/juːˈkærioʊts, -əts/) are organisms whose cells have a nucleus + enclosed within a nuclear envelope.[1][2][3] They belong to the group of + organisms Eukaryota or Eukarya; their name comes from the Greek εὖ (eu, + "well" or "good") and κάρυον (karyon, "nut" or "kernel").[4] The domain + Eukaryota makes up one of the three domains of life; bacteria and archaea + (both prokaryotes) make up the other two domains.[5][6] The eukaryotes are + usually now regarded as having emerged in the Archaea or as a sister of the + Asgard archaea.[7][8] This implies that there are only two domains of life, + Bacteria and Archaea, with eukaryotes incorporated among archaea.[9][10] + Eukaryotes represent a small minority of the number of organisms;[11] + however, due to their generally much larger size, their collective global + biomass is estimated to be about equal to that of prokaryotes.[11] + Eukaryotes emerged approximately 2.3–1.8 billion years ago, during the + Proterozoic eon, likely as flagellated phagotrophs.[12][13] + |] + "https://en.wikipedia.org/wiki/Eukaryote", + + CalendarEntry (1.2 & billionYearsAgo) Nothing + "Red and brown algae" + "" + [text| + These organisms have more complex cellular structures than bacteria do. Like + cyanobacteria, they contain phycobilin pigments as well as various forms of + chlorophyll. + |] + "https://www.scientificamerican.com/article/timeline-of-photosynthesis-on-earth/", + + CalendarEntry (0.75 & billionYearsAgo) Nothing + "Green algae" + "" + [text| + Green algae do better than red and brown algae in the strong light of + shallow water. They make do without phycobilins. + |] + "https://www.scientificamerican.com/article/timeline-of-photosynthesis-on-earth/", + + CalendarEntry (0.475 & billionYearsAgo) Nothing + "First land plants" + "" + [text| + Mosses and liverworts descended from green algae. Lacking vascular structure + (stems and roots) to pull water from the soil, they are unable to grow + tall. + |] + "https://www.scientificamerican.com/article/timeline-of-photosynthesis-on-earth/", + + CalendarEntry (0.423 & billionYearsAgo) Nothing + "Vascular plants" + "" + [text| + These are literally garden-variety plants, such as ferns, grasses, trees and + cacti. They are able to grow tall canopies to capture more light. + |] + "https://www.scientificamerican.com/article/timeline-of-photosynthesis-on-earth/", + + CalendarEntry (750 & millionYearsAgo) Nothing + "Bones and shells" + "" + [text| + A series of spectacularly preserved, 750-million-year-old fossils represent + the microscopic origins of biomineralization, or the ability to convert + minerals into hard, physical structures. This process is what makes bones, + shells, teeth and hair possible, literally shaping the animal kingdom and + even Earth itself. + + The fossils were pried from ancient rock formations in Canada's Yukon by + earth scientists Francis Macdonald and Phoebe Cohen of Harvard University. + In a June Geology paper, they describe their findings as providing "a unique + window into the diversity of early eukaryotes." + + Using molecular clocks and genetic trees to reverse-engineer evolutionary + histories, previous research placed the beginning of biomineralization at + about 750 million years ago. Around that time, the fossil record gets + suggestive, turning up vase-shaped amoebas with something like scales in + their cell walls, algae with cell walls possibly made from calcium carbonate + and sponge-like creatures with seemingly mineralized bodies. + |] + "https://www.wired.com/2011/06/first-shells/", + + CalendarEntry (440 & millionYearsAgo) Nothing + "Fish with jaws" + "" + [text| + Prehistoric armoured fishes called placoderms were the first fishes to have + jaws. They arose some time in the Silurian Period, about 440 million years + ago, to become the most abundant and diverse fishes of their day. + + Placoderms dominated the oceans, rivers and lakes for some 80 million years, + before their sudden extinction around 359 million years ago. This is possibly + due to the depletion of trace elements in our oceans. + |] + "", + + CalendarEntry (518 & millionYearsAgo) Nothing + "Vertebrates" + "Animals with backbones" + [text| + Vertebrates (/ˈvɜːrtəbrɪts, -ˌbreɪts/)[3] comprise all animal taxa within + the subphylum Vertebrata (/ˌvɜːrtəˈbreɪtə/)[4] (chordates with backbones), + including all mammals, birds, reptiles, amphibians, and fish. Vertebrates + represent the overwhelming majority of the phylum Chordata, with currently + about 69,963 species described.[5] + |] + "", + + CalendarEntry (385 & millionYearsAgo) Nothing + "Insects" + "" + [text| + Comprising up to 10 million living species, insects today can be found on + all seven continents and inhabit every terrestrial niche imaginable. But + according to the fossil record, they were scarce before about 325 million + years ago, outnumbered by their arthropod cousins the arachnids (spiders, + scorpions and mites) and myriapods (centipedes and millipedes). + + The oldest confirmed insect fossil is that of a wingless, silverfish-like + creature that lived about 385 million years ago. It’s not until about 60 + million years later, during a period of the Earth’s history known as the + Pennsylvanian, that insect fossils become abundant. + |] + "https://earth.stanford.edu/news/insects-took-when-they-evolved-wings", + + CalendarEntry (368 & millionYearsAgo) Nothing + "Amphibians" + "" + [text| + The earliest well-known amphibian, Ichthyostega, was found in Late Devonian + deposits in Greenland, dating back about 363 million years. The earliest + amphibian discovered to date is Elginerpeton, found in Late Devonian rocks + of Scotland dating to approximately 368 million years ago. The later + Paleozoic saw a great diversity of amphibians, ranging from small legless + swimming forms (Aistopoda) to bizarre "horned" forms (Nectridea). Other + Paleozoic amphibians more or less resembled salamanders outwardly but + differed in details of skeletal structure. Exactly how to classify these + fossils, and how they might be related to living amphibians, is still + debated by paleontologists. Shown at the right is Phlegethontia, an aistopod + from the Pennsylvanian. + + The familiar frogs, toads, and salamanders have been present since at least + the Jurassic Period. (The fossil frog pictured to the left is much younger, + coming from the Eocene, only 45 to 55 million years ago). Fossil caecilians + are very rare; until recently the oldest known caecilians were Cenozoic in + age (that is, less than 65 million years old), but recent finds have pushed + back the ancestry of the legless caecilians to Jurassic ancestors that had + short legs. The rarity of fossil caecilians is probably due to their + burrowing habitat and reduced skeleton, both of which lessen the chances of + preservation. + |] + "https://ucmp.berkeley.edu/vertebrates/tetrapods/amphibfr.html", + + CalendarEntry (320 & millionYearsAgo) Nothing + "Reptiles" + "" + [text| + Reptiles, in the traditional sense of the term, are defined as animals that + have scales or scutes, lay land-based hard-shelled eggs, and possess + ectothermic metabolisms. + + Though few reptiles today are apex predators, many examples of apex reptiles + have existed in the past. Reptiles have an extremely diverse evolutionary + history that has led to biological successes, such as dinosaurs, pterosaurs, + plesiosaurs, mosasaurs, and ichthyosaurs. + |] + [text| + https://en.wikipedia.org/wiki/Evolution_of_reptiles + https://www.thoughtco.com/the-first-reptiles-1093767 + |], + + CalendarEntry (335 & millionYearsAgo) Nothing + "Pangea forms" + "" + [text| + Pangaea or Pangea (/pænˈdʒiː.ə/)[1] was a supercontinent that existed during + the late Paleozoic and early Mesozoic eras.[2] It assembled from the earlier + continental units of Gondwana, Euramerica and Siberia during the + Carboniferous approximately 335 million years ago, and began to break apart + about 200 million years ago, at the end of the Triassic and beginning of the + Jurassic.[3] In contrast to the present Earth and its distribution of + continental mass, Pangaea was centred on the Equator and surrounded by the + superocean Panthalassa and the Paleo-Tethys and subsequent Tethys Oceans. + Pangaea is the most recent supercontinent to have existed and the first to + be reconstructed by geologists. + |] + "https://en.wikipedia.org/wiki/Pangaea", + + CalendarEntry (243 & millionYearsAgo) Nothing + "Dinosaurs" + "" + [text| + For the past twenty years, Eoraptor has represented the beginning of the Age + of Dinosaurs. This controversial little creature–found in the roughly + 231-million-year-old rock of Argentina–has often been cited as the earliest + known dinosaur. But Eoraptor has either just been stripped of that title, or + soon will be. A newly-described fossil found decades ago in Tanzania extends + the dawn of the dinosaurs more than 10 million years further back in time. + + Named Nyasasaurus parringtoni, the roughly 243-million-year-old fossils + represent either the oldest known dinosaur or the closest known relative to + the earliest dinosaurs. The find was announced by University of Washington + paleontologist Sterling Nesbitt and colleagues in Biology Letters, and I + wrote a short news item about the discovery for Nature News. The paper + presents a significant find that is also a tribute to the work of Alan + Charig–who studied and named the animal, but never formally published a + description–but it isn’t just that. The recognition of Nyasasaurus right + near the base of the dinosaur family tree adds to a growing body of evidence + that the ancestors of dinosaurs proliferated in the wake of a catastrophic + mass extinction. + |] + [text| + https://www.smithsonianmag.com/science-nature/scientists-discover-oldest-known-dinosaur-152807497/ + |], + + CalendarEntry (210 & millionYearsAgo) Nothing + "Mammals" + "" + [text| + The earliest known mammals were the morganucodontids, tiny shrew-size + creatures that lived in the shadows of the dinosaurs 210 million years ago. + They were one of several different mammal lineages that emerged around that + time. All living mammals today, including us, descend from the one line that + survived. + |] + "https://www.nationalgeographic.com/science/article/rise-mammals", + + CalendarEntry (150 & millionYearsAgo) Nothing + "Birds" + "" + [text| + The first birds had sharp teeth, long bony tails and claws on their hands. + The clear distinction we see between living birds and other animals did not + exist with early birds. The first birds were in fact more like small + dinosaurs than they were like any bird today. + + The earliest known (from fossils) bird is the 150-million-year-old + Archaeopteryx, but birds had evolved before then. A range of birds with more + advanced features appeared soon after Archaeopteryx. One group gave rise to + modern birds in the Late Cretaceous. + |] + "https://australian.museum/learn/dinosaurs/the-first-birds/", + + CalendarEntry (130 & millionYearsAgo) Nothing + "Flowers" + "" + [text| + Today, plants with flowers--called angiosperms--dominate the landscape. + Around 80 percent of green plants alive today, from oak trees to grass, are + flowering plants. In all of these plants, flowers are part of the + reproductive system. But 130 million years ago, flowering plants were rare. + Most plants reproduced with spores, found today on ferns, or with seeds and + cones, found today on pine trees. The plant fossils found in Liaoning, + China, show evidence of plants with spores or seeds--and perhaps one of the + first flowering plants. + + Researchers have found an ancient plant in Liaoning, Archaefructus, that has + very small, simple flowers and could be one of the first flowering plants. + Archaefructus lived around 130 million years ago and probably grew in or + near the water. + |] + "https://www.amnh.org/exhibitions/dinosaurs-ancient-fossils/liaoning-diorama/when-flowers-first-bloomed", + + CalendarEntry (85 & millionYearsAgo) Nothing + "Tyranosaurids" + "The Tyrant Lizards" + [text| + The name says it all. This group of huge carnivores must have tyrannically + ruled the land during the last part of the Cretaceous, 85 to 65 million + years ago. Short but deep jaws with banana-sized sharp teeth, long hind + limbs, small beady eyes, and tiny forelimbs (arms) typify a tyrannosaur. The + Tyrannosauridae included such similar animals (in rough order of increasing + size) as Albertosaurus, Gorgosaurus, Daspletosaurus, Tarbosaurus, and of + course Tyrannosaurus rex. + + T. rex was one of the largest terrestrial carnivores of all time. It stood + approximately 15 feet high and was about 40 feet in length, roughly six tons + in weight. In its large mouth were six-inch long, sharp, serrated teeth. + + Just about two dozen good specimens of these animals have been found and + these finds are from highly restricted areas in western North America. Henry + Fairfield Osborn, of the American Museum of Natural History in New York + City, first described Tyrannosaurus rex in 1905. This first specimen of + Tyrannosaurus is now on display at the Carnegie Museum of Natural History in + Pittsburgh, Pennsylvania. + |] + "", + + CalendarEntry (445 & millionYearsAgo) Nothing + "The first mass extinction" + "Fluctuating sea levels cause mass die-off of marine invertebrates" + [text| + The earliest known mass extinction, the Ordovician Extinction, took place at + a time when most of the life on Earth lived in its seas. Its major + casualties were marine invertebrates including brachiopods, trilobites, + bivalves and corals; many species from each of these groups went extinct + during this time. The cause of this extinction? It’s thought that the main + catalyst was the movement of the supercontinent Gondwana into Earth’s + southern hemisphere, which caused sea levels to rise and fall repeatedly + over a period of millions of years, eliminating habitats and species. The + onset of a late Ordovician ice age and changes in water chemistry may also + have been factors in this extinction. + |] + "https://www.amnh.org/shelf-life/six-extinctions", + + CalendarEntry (370 & millionYearsAgo) Nothing + "Late Devonian Extinction" + "The Kellwasser Event and the Hangenberg Event combine to cause an enormous loss in biodiversity" + [text| + Given that it took place over a huge span of time—estimates range from + 500,000 to 25 million years—it isn’t possible to point to a single cause for + the Devonian extinction, though some suggest that the amazing spread of + plant life on land during this time may have changed the environment in ways + that made life harder, and eventually impossible, for the species that died + out. + + The brunt of this extinction was borne by marine invertebrates. As in the + Ordovician Extinction, many species of corals, trilobites, and brachiopods + vanished. Corals in particular were so hard hit that they were nearly wiped + out, and didn’t recover until the Mesozoic Era, nearly 120 million years + later. Not all vertebrate species were spared, however; the early bony + fishes known as placoderms met their end in this extinction. + |] + "https://www.amnh.org/shelf-life/six-extinctions", + + CalendarEntry (252 & millionYearsAgo) Nothing + "The Great Dying" + "Mass extinction kills more than 95 percent of marine species and 70 percent of land-dwelling vertebrates" + [text| + So many species were wiped out by this mass extinction it took more than 10 + million years to recover from the huge blow to global biodiversity. This + extinction is thought to be the result of a gradual change in climate, + followed by a sudden catastrophe. Causes including volcanic eruptions, + asteroid impacts, and a sudden release of greenhouse gasses from the + seafloor have been proposed, but the mechanism behind the Great Dying + remains a mystery. + |] + "https://www.amnh.org/shelf-life/six-extinctions", + + CalendarEntry (201 & millionYearsAgo) Nothing + "Triassic-Jurassic Extinction" + "Death of more than a third of marine species and of most large amphibians" + [text| + This extinction occurred just a few millennia before the breakup of the + supercontinent of Pangaea. While its causes are not definitively + understood—researchers have suggested climate change, an asteroid impact, or + a spate of enormous volcanic eruptions as possible culprits—its effects are + indisputable. + + More than a third of marine species vanished, as did most large amphibians + of the time, as well as many species related to crocodiles and dinosaurs. + |] + "https://www.amnh.org/shelf-life/six-extinctions", + + CalendarEntry (66 & millionYearsAgo) Nothing + "Dinosaurs extinct" + "Mammals take over land & sea" + [text| + An asteroid more than 6 miles across strikes the Yucatan Peninsula, + triggering the fifth mass extinction in the world’s history. + + Some of the debris thrown into the atmosphere returned to Earth, the + friction turning the air into an oven and sparking forest fires as it landed + all over the world. The intensity of the heat pulse gave way to a prolonged + impact winter, the sky blotted out by soot and ash as temperatures fell. + + More than 75 percent of species known from the end of the Cretaceous period, + 66 million years ago, didn’t make it to the following Paleogene period. The + geologic break between the two is called the K-Pg boundary, and beaked birds + were the only dinosaurs to survive the disaster.|] + [text| + https://www.smithsonianmag.com/science-nature/why-birds-survived-and-dinosaurs-went-extinct-after-asteroid-hit-earth-180975801/, + https://www.amnh.org/shelf-life/six-extinctions + |], + + CalendarEntry (27.5 & millionYearsAgo) Nothing + "Apes and monkeys split" + "" + [text| + Studies of clock-like mutations in primate DNA have indicated that the split + between apes and Old World monkeys occurred between 30 million and 25 + million years ago. + |] + "https://www.nsf.gov/news/news_summ.jsp?cntn_id=127930", + + CalendarEntry (12.1 & millionYearsAgo) Nothing + "Humans and chimpanzees split" + "" + [text| + A 2016 study analyzed transitions at CpG sites in genome sequences, which + exhibit a more clocklike behavior than other substitutions, arriving at an + estimate for human and chimpanzee divergence time of 12.1 million years.[20] + |] + [text| + https://en.wikipedia.org/wiki/Chimpanzee%E2%80%93human_last_common_ancestor + |], + + CalendarEntry (4.4 & millionYearsAgo) Nothing + "Humans first walk upright" + "" + [text| + The earliest hominid with the most extensive evidence for bipedalism is the 4.4-million-year-old Ardipithecus ramidus. + |] + [text| + https://www.smithsonianmag.com/science-nature/becoming-human-the-evolution-of-walking-upright-13837658/ + |], + + CalendarEntry (300 & thousandYearsAgo) Nothing + "Modern humans evolve" + "" + [text| + Among the oldest known remains of Homo sapiens are those found at the + Omo-Kibish I archaeological site in south-western Ethiopia, dating to about + 233,000[2] to 196,000 years ago,[3] the Florisbad site in South Africa, + dating to about 259,000 years ago, and the Jebel Irhoud site in Morocco, + dated about 300,000 years ago. + |] + [text| + https://en.wikipedia.org/wiki/Early_modern_human + |], + + CalendarEntry (100 & thousandYearsAgo) Nothing + "Human migration out of Africa" + "" + [text| + Between 70,000 and 100,000 years ago, Homo sapiens began migrating from the + African continent and populating parts of Europe and Asia. They reached the + Australian continent in canoes sometime between 35,000 and 65,000 years ago. + + Map of the world showing the spread of Homo sapiens throughout the Earth + over time. + |] + [text| + https://www.khanacademy.org/humanities/world-history/world-history-beginnings/origin-humans-early-societies/a/where-did-humans-come-from + |], + + CalendarEntry (600 & millionYearsAgo) Nothing + "Multicellular life" + "" + [text| + |] + "", + + CalendarEntry (2.6 & millionYearsAgo) Nothing + "First Stone Tools" + [text| + Mode I: The Oldowan Industry + Stone flakes with sharp edges for cutting + |] + [text| + The earliest known Oldowan tools yet found date from 2.6 million years ago, + during the Lower Palaeolithic period, and have been uncovered at Gona in + Ethiopia.[16] After this date, the Oldowan Industry subsequently spread + throughout much of Africa, although archaeologists are currently unsure + which Hominan species first developed them, with some speculating that it + was Australopithecus garhi, and others believing that it was in fact Homo + habilis.[17] + + Homo habilis was the hominin who used the tools for most of the Oldowan in + Africa, but at about 1.9-1.8 million years ago Homo erectus inherited them. + The Industry flourished in southern and eastern Africa between 2.6 and 1.7 + million years ago, but was also spread out of Africa and into Eurasia by + travelling bands of H. erectus, who took it as far east as Java by 1.8 + million years ago and Northern China by 1.6 million years ago. + |] + "", + + CalendarEntry (1.8 & millionYearsAgo) Nothing + "First major transition in stone tool technology" + [text| + Mode II: The Acheulean Industry + Stone hand-axes shaped symmetrically from two sides + |] + [text| + From the Konso Formation of Ethiopia, Acheulean hand-axes are dated to about + 1.5 million years ago using radiometric dating of deposits containing + volcanic ashes.[6] Acheulean tools in South Asia have also been found to be + dated as far as 1.5 million years ago.[7] However, the earliest accepted + examples of the Acheulean currently known come from the West Turkana region + of Kenya and were first described by a French-led archaeology team.[8] These + particular Acheulean tools were recently dated through the method of + magnetostratigraphy to about 1.76 million years ago, making them the oldest + not only in Africa but the world.[9] The earliest user of Acheulean tools + was Homo ergaster, who first appeared about 1.8 million years ago. Not all + researchers use this formal name, and instead prefer to call these users + early Homo erectus.[3] + |] + "", + + CalendarEntry (160 & thousandYearsAgo) Nothing + "Second major transition in stone tool technology" + [text| + Mode III: The Levallois technique; The Mousterian Industry + Stone scrapers, knives, and projectile points + |] + [text| + Levallois is a "prepared-core" technique: one face of a stone core is fully + shaped by knapping in perparation. Then a large sharp flake is created by + cracking off the entire prepared face in one final stroke. + + The technique is first found in the Lower Palaeolithic but is most commonly + associated with the Neanderthal Mousterian industries of the Middle + Palaeolithic. In the Levant, the Levallois technique was also used by + anatomically modern humans during the Middle Stone Age. In North Africa, the + Levallois technique was used in the Middle Stone Age, most notably in the + Aterian industry to produce very small projectile points. While Levallois + cores do display some variability in their platforms, their flake production + surfaces show remarkable uniformity. As the Levallois technique is + counterintuitive, teaching the process is necessary and thus language is a + prerequisite for such technology.[2] + + The Mousterian (or Mode III) is a techno-complex (archaeological industry) + of stone tools, associated primarily with the Neanderthals in Europe, and to + a lesser extent the earliest anatomically modern humans in North Africa and + West Asia. The Mousterian largely defines the latter part of the Middle + Paleolithic, the middle of the West Eurasian Old Stone Age. It lasted + roughly from 160,000 to 40,000 BP. If its predecessor, known as Levallois or + Levallois-Mousterian, is included, the range is extended to as early as c. + 300,000–200,000 BP.[2] The main following period is the Aurignacian (c. + 43,000–28,000 BP) of Homo sapiens. + |] + "", + + CalendarEntry (115 & thousandYearsAgo) (Just $ 11.7 & thousandYearsAgo) + "The Ice Age begins" + "Glaciers cover most land on Earth, joining Asia to North America" + [text| + The Last Glacial Period (LGP), also known colloquially as the last ice age + or simply ice age,[1] occurred from the end of the Eemian to the end of the + Younger Dryas, encompassing the period c. 115,000 – c. 11,700 years ago. The + LGP is part of a larger sequence of glacial and interglacial periods known + as the Quaternary glaciation which started around 2,588,000 years ago and is + ongoing.[2] The definition of the Quaternary as beginning 2.58 million years + ago (Mya) is based on the formation of the Arctic ice cap. The Antarctic ice + sheet began to form earlier, at about 34 Mya, in the mid-Cenozoic + (Eocene–Oligocene extinction event). The term Late Cenozoic Ice Age is used + to include this early phase.[3] + |] + "https://en.wikipedia.org/wiki/Last_Glacial_Period", + + CalendarEntry (50 & thousandYearsAgo) Nothing + "Third major transition in stone tool technology" + [text| + Mode IV: The Aurignacian Industry + Long stone blades + |] + [text| + The widespread use of long blades (rather than flakes) of the Upper + Palaeolithic Mode 4 industries appeared during the Upper Palaeolithic + between 50,000 and 10,000 years ago, although blades were produced in small + quantities much earlier by Neanderthals.[20] The Aurignacian culture seems + to have been the first to rely largely on blades.[21] The use of blades + exponentially increases the efficiency of core usage compared to the + Levallois flake technique, which had a similar advantage over Acheulean + technology which was worked from cores. + |] + "https://en.wikipedia.org/wiki/Stone_tool#Mode_IV:_The_Aurignacian_Industry", + + CalendarEntry (35 & thousandYearsAgo) Nothing + "Last major transition in stone tool technology" + [text| + Mode V: The Microlithic Industries + Stone blades fastened to wood or bone handles + |] + [text| + Mode 5 stone tools involve the production of microliths, which were + used in composite tools, mainly fastened to a shaft.[22] Examples include + the Magdalenian culture. Such a technology makes much more efficient use of + available materials like flint, although required greater skill in + manufacturing the small flakes. Mounting sharp flint edges in a wood or bone + handle is the key innovation in microliths, essentially because the handle + gives the user protection against the flint and also improves leverage of + the device. + |] + "https://en.wikipedia.org/wiki/Stone_tool#Mode_V:_The_Microlithic_Industries" + , + + CalendarEntry (12 & thousandYearsAgo) Nothing + "Agriculture leads to permanent settlements" + "Neolithic age (\"new stone age\")" + [text| + Wild grains were collected and eaten from at least 105,000 years ago.[2] + However, domestication did not occur until much later. The earliest evidence + of small-scale cultivation of edible grasses is from around 21,000 BC with + the Ohalo II people on the shores of the Sea of Galilee.[3] By around 9500 + BC, the eight Neolithic founder crops – emmer wheat, einkorn wheat, hulled + barley, peas, lentils, bitter vetch, chickpeas, and flax – were cultivated + in the Levant.[4] Rye may have been cultivated earlier, but this claim + remains controversial.[5] Rice was domesticated in China by 6200 BC[6] with + earliest known cultivation from 5700 BC, followed by mung, soy and azuki + beans. Rice was also independently domesticated in West Africa and + cultivated by 1000 BC.[7][8] Pigs were domesticated in Mesopotamia around + 11,000 years ago, followed by sheep. Cattle were domesticated from the wild + aurochs in the areas of modern Turkey and India around 8500 BC. Camels were + domesticated late, perhaps around 3000 BC. + |] + "https://en.wikipedia.org/wiki/History_of_agriculture", + + CalendarEntry (6.5 & thousandYearsAgo) Nothing + "First copper tools" + "" + "" + "", + + CalendarEntry (5.3 & thousandYearsAgo) Nothing + "First bronze tools, first written language" + "The Bronze Age" + "" + "", + + CalendarEntry (3000 & yearsBeforeCommonEra) (Just $ 2350 & yearsBeforeCommonEra) + "Corded Ware culture" + "Indo-European languages spread across Europe and Asia" + [text| + The Corded Ware culture comprises a broad archaeological horizon of Europe + between ca. 3000 BCE – 2350 BCE, thus from the late Neolithic, through the + Copper Age, and ending in the early Bronze Age.[2] Corded Ware culture + encompassed a vast area, from the contact zone between the Yamnaya culture + and the Corded Ware culture in south Central Europe, to the Rhine on the + west and the Volga in the east, occupying parts of Northern Europe, Central + Europe and Eastern Europe.[2][3] The Corded Ware culture is thought to have + originated from the westward migration of Yamnaya-related people from the + steppe-forest zone into the territory of late Neolithic European cultures + such as the Globular Amphora and Funnelbeaker cultures,[4][5][6] and is + considered to be a likely vector for the spread of many of the Indo-European + languages in Europe and Asia.[1][7][8][9] + + Corded Ware encompassed most of continental northern Europe from the Rhine + on the west to the Volga in the east, including most of modern-day Germany, + the Netherlands, Denmark, Poland, Lithuania, Latvia, Estonia, Belarus, Czech + Republic, Austria, Hungary, Slovakia, Switzerland, northwestern Romania, + northern Ukraine, and the European part of Russia, as well as coastal Norway + and the southern portions of Sweden and Finland.[2] In the Late + Eneolithic/Early Bronze Age, it encompassed the territory of nearly the + entire Balkan Peninsula, where Corded Ware mixed with other steppe + elements.[11] + + Archaeologists note that Corded Ware was not a "unified culture," as Corded + Ware groups inhabiting a vast geographical area from the Rhine to Volga seem + to have regionally specific subsistence strategies and economies.[2]: 226  + There are differences in the material culture and in settlements and + society.[2] At the same time, they had several shared elements that are + characteristic of all Corded Ware groups, such as their burial practices, + pottery with "cord" decoration and unique stone-axes.[2] + |] + "", + + CalendarEntry (2800 & yearsBeforeCommonEra) (Just $ 1800 & yearsBeforeCommonEra) + "Bell Beaker culture" + [text| + copper daggers, v-perforated buttons, stone wrist-guards + copper, bronze, and gold working + long-distance exchange networks, archery + social stratification and the emergence of regional elites + |] + [text| + The Bell Beaker culture (also described as the Bell Beaker complex or Bell + Beaker phenomenon) is an archaeological culture named after the + inverted-bell beaker drinking vessel used at the very beginning of the + European Bronze Age. Arising from around 2800 BC, it lasted in Britain until + as late as 1800 BC[1][2] but in continental Europe only until 2300 BC, when + it was succeeded by the Unetice culture. The culture was widely dispersed + throughout Western Europe, being present in many regions of Iberia and + stretching eastward to the Danubian plains, and northward to the islands of + Great Britain and Ireland, and was also present in the islands of Sicily and + Sardinia and some small coastal areas in north-western Africa. The Bell + Beaker phenomenon shows substantial regional variation, and a study[3] from + 2018 found that it was associated with genetically diverse populations. + + In its mature phase, the Bell Beaker culture is understood as not only a + collection of characteristic artefact types, but a complex cultural + phenomenon involving metalwork in copper and gold, long-distance exchange + networks, archery, specific types of ornamentation, and (presumably) shared + ideological, cultural and religious ideas, as well as social stratification + and the emergence of regional elites.[6][7] A wide range of regional + diversity persists within the widespread late Beaker culture, particularly + in local burial styles (including incidences of cremation rather than + burial), housing styles, economic profile, and local ceramic wares + (Begleitkeramik). Nonetheless, according to Lemercier (2018) the mature + phase of the Beaker culture represents "the appearance of a kind of Bell + Beaker civilization of continental scale."[8] + + Bell Beaker people took advantage of transport by sea and rivers, creating a + cultural spread extending from Ireland to the Carpathian Basin and south + along the Atlantic coast and along the Rhône valley to Portugal, North + Africa, and Sicily, even penetrating northern and central Italy.[50] Its + remains have been found in what is now Portugal, Spain, France (excluding + the central massif), Ireland and Great Britain, the Low Countries and + Germany between the Elbe and Rhine, with an extension along the upper Danube + into the Vienna Basin (Austria), Hungary and the Czech Republic, with + Mediterranean outposts on Sardinia and Sicily; there is less certain + evidence for direct penetration in the east. + |] + "https://en.wikipedia.org/wiki/Bell_Beaker_culture", + + CalendarEntry (11.7 & thousandYearsAgo) Nothing + "Ice Age ends" + "" + "" + "https://en.wikipedia.org/wiki/Last_Glacial_Period", + + CalendarEntry (1600 & yearsBeforeCommonEra) Nothing + "Dynastic China" + "History begins" + [text| + The earliest known written records of the history of China date from as + early as 1250 BC, from the Shang dynasty (c. 1600–1046 BC), during the king + Wu Ding's reign + + The state-sponsored Xia–Shang–Zhou Chronology Project dated them from c. + 1600 to 1046 BC based on the carbon 14 dates of the Erligang site. + |] + "", + + CalendarEntry (480 & yearsBeforeCommonEra) Nothing + "Old Testament, Buddha" + "" + "" + "", + + CalendarEntry (6 & yearsBeforeCommonEra) Nothing + "Christ born" + "" + "" + "", + + -- CalendarEntry (300 & yearsBeforeCommonEra) Nothing + -- "Eratosthenes calculates the circumference of Earth" + -- "" + -- "" + -- "", + + CalendarEntry (theYear 570) Nothing + "Muhammad born" + "" + "" + "", + + CalendarEntry (theYear 1492) Nothing + "Columbus arrives in America" + "" + "" + "" + ] diff --git a/src/countdown.hs b/src/countdown.hs new file mode 100755 index 0000000..1910bec --- /dev/null +++ b/src/countdown.hs @@ -0,0 +1,523 @@ +#!/usr/bin/env stack +{- stack script --resolver lts-19.23 --install-ghc -} +{-# OPTIONS_GHC + -Wall + -Wno-unused-imports + -Wno-unused-top-binds + -Wno-name-shadowing +#-} +{-# language NoImplicitPrelude #-} +{-# language RecordWildCards #-} +{-# language FlexibleContexts #-} +{-# language TemplateHaskell #-} +{-# language ViewPatterns #-} +{-# language OverloadedStrings #-} +import Rebase.Prelude hiding (toList, on, (<+>), Max) +import qualified Rebase.Prelude as Prelude +import Control.Lens hiding ((<|)) +import Data.Foldable (toList) +import Data.Ratio +import Text.Printf +import Graphics.Vty +import Data.Time.LocalTime +import Control.Monad.RWS +import Data.Time.Calendar.OrdinalDate +import qualified Data.Text as Text +import Data.Text.Format.Numbers +import Rebase.Data.Map.Strict (Map) +import qualified Rebase.Data.Map.Strict as Map + +import Brick +import Brick.Types +import Data.Text (unpack) +import Control.Lens +import Control.Monad (void, forever) +import Control.Concurrent (threadDelay, forkIO) +import qualified Graphics.Vty as V +import Brick.Widgets.ProgressBar as P +import Brick.BChan +import Brick.Widgets.Center +import Brick.Widgets.Border +import Brick.Main + ( App(..) + , showFirstCursor + , customMain + , continue + , halt + ) +import Brick.AttrMap + ( attrMap + ) +import Brick.Types + ( Widget + , Next + , EventM + , BrickEvent(..) + ) +import Brick.Widgets.Core + ( (<=>) + , str + ) +import Brick.AttrMap as A +import Brick.Util (fg, bg, on, clamp) +import Brick.Widgets.Core +import Brick.Widgets.Table + +import CosmicCalendar +import CosmicCalendarEvents + +data CustomEvent = TimeChanged ZonedTime deriving Show + +data St = + St { _stLastBrickEvent :: Maybe (BrickEvent () CustomEvent) + , _stClockTime :: LocalTime + , _stDisplayTime :: LocalTime + , _stNextEvent :: Maybe UTCTime + , _stPaused :: Bool + , _stShowConversion :: Bool + } + +makeLenses ''St + +yearNumber :: LocalTime -> Integer +yearNumber (LocalTime t _) = y + where + (y, _, _) = toGregorian t + +yearEnd :: LocalTime -> LocalTime +yearEnd (LocalTime d _) = LocalTime d' t' + where + d' = fromGregorian (y + 1) 1 1 + t' = TimeOfDay 0 0 0 + (y, _, _) = toGregorian d + + +dayNumOfYear :: LocalTime -> Int +dayNumOfYear = snd . toOrdinalDate . localDay + +pluralize :: (Num n, Eq n) => n -> String +pluralize 1 = "" +pluralize _ = "s" + +pluralizeVerb :: (Num n, Eq n) => n -> String +pluralizeVerb 1 = "s" +pluralizeVerb _ = "" + +drawUI :: St -> [Widget ()] +drawUI st = [a] + where + a = vBox [ + -- (str $ "Last event: " <> (show $ st ^. stLastBrickEvent)), + -- (str "\n"), + (str "\n"), + (countdownWidget (st ^. stShowConversion) (isSimulatedTime st) $ st ^. stDisplayTime) + ] + +showTime' :: Bool -> NominalDiffTime -> String +showTime' True 1 = printf "%-3s second" ("1" :: Text) +showTime' True t | t < 60 = printf "%.1f seconds" (realToFrac t :: Float) +showTime' _ t = showTime t + +showTime :: NominalDiffTime -> String +showTime t | t < 1 = printf "%.3f seconds" (realToFrac t :: Float) +showTime t | t == 1 = "1 second" +-- showTime t | t < 10 = formatTime defaultTimeLocale "%2Es seconds" t -- BUG! Doesn't respect parameter at all! +showTime t | t < 60 = printf "%.1f seconds" (realToFrac t :: Float) +showTime t | t == 60 = formatTime defaultTimeLocale "%M minute" t +showTime t | t < 60*2 = formatTime defaultTimeLocale "%M minute %Ss" t +showTime t | t < 60*10 = formatTime defaultTimeLocale "%M minutes %Ss" t +showTime t | t < 60*60 = formatTime defaultTimeLocale "%M minutes" t +showTime t | t == 60*60 = "1 hour" +showTime t | t < 60*60*2 = formatTime defaultTimeLocale "%H hour %Mm" t +showTime t | t < 60*60*24 = formatTime defaultTimeLocale "%H hours %Mm" t +showTime t | t == 60*60*24 = formatTime defaultTimeLocale "%d day" t +showTime t | t < 60*60*24*2 = formatTime defaultTimeLocale "%d day %Hh" t +showTime t | t == 60*60*24*7 = formatTime defaultTimeLocale "%d days" t +showTime t | t < 60*60*24*10 = formatTime defaultTimeLocale "%d days %Hh" t +showTime t = formatTime defaultTimeLocale "%d days" t +-- showTime _ t = formatTime defaultTimeLocale "%w weeks %D days" t + +yearsToCosmicTime :: Integral i => i -> NominalDiffTime +yearsToCosmicTime = (/ (realToFrac ageOfUniverseInYears)) . (* lengthOfYear) . realToFrac + +showCosmicYears :: Integer -> Widget n +showCosmicYears = str . showTime . yearsToCosmicTime + +toCosmicTime :: NominalDiffTime -> Rational +toCosmicTime t = realToFrac ageOfUniverseInYears * (realToFrac $ t // yearLength) :: Rational + where + yearLength = daysPerYear * nominalDay + x // y = fromRational $ toRational x / toRational y :: Double + +showCosmicTime :: NominalDiffTime -> String +showCosmicTime n = showLarge (fromRational $ toCosmicTime n) ++ " years" + +conversionTableRowFromCosmicSeconds :: NominalDiffTime -> [Widget n] +conversionTableRowFromCosmicSeconds n = [cosmicTime, realTime] + where + realTime = str $ showCosmicTime n + cosmicTime = str $ showTime n + +cosmicConversion' :: Widget n +cosmicConversion' = renderTable $ + table + [ + conversionTableRowFromCosmicSeconds $ 30 * 24 * 60 * 60, + conversionTableRowFromCosmicSeconds $ 7 * 24 * 60 * 60, + conversionTableRowFromCosmicSeconds $ 24 * 60 * 60, + conversionTableRowFromCosmicSeconds $ 60 * 60, + conversionTableRowFromCosmicSeconds $ 60, + conversionTableRowFromCosmicSeconds $ 1 + ] + +cosmicConversion :: Widget n +cosmicConversion = renderTable $ + table + [ + [str "1 billion years" , showCosmicYears $ 1000 * 1000 * 1000], + [str "100 million years" , showCosmicYears $ 100 * 1000 * 1000], + [str "10 million years" , showCosmicYears $ 10 * 1000 * 1000], + [str "1 million years" , showCosmicYears $ 1000 * 1000], + [str "100 thousand years" , showCosmicYears $ 100 * 1000], + [str "10 thousand years" , showCosmicYears $ 10 * 1000], + [str "1 thousand years" , showCosmicYears 1000], + [str "100 years" , showCosmicYears 100], + [str "10 years" , showCosmicYears 10], + [str "1 year" , showCosmicYears 1] + ] + +showLarge :: Double -> String +showLarge n | n >= 10 * 1000 * 1000 * 1000 = printf "%.0f billion" (n / (1000 * 1000 * 1000)) +showLarge n | n >= 1000 * 1000 * 1000 = printf "%.1f billion" (n / (1000 * 1000 * 1000)) +showLarge n | n >= 10 * 1000 * 1000 = printf "%.0f million" (n / (1000 * 1000)) +showLarge n | n >= 1000 * 1000 = printf "%.1f million" (n / (1000 * 1000)) +showLarge n | n >= 10 * 1000 = printf "%.0f thousand" (n / 1000) +showLarge n | n >= 10 = unpack $ commasF 0 n +showLarge n = printf "%.3f" n + +countdownWidget :: Bool -> Bool -> LocalTime -> Widget n +countdownWidget showConversion isSimulated t = + (border $ vBox [ + (hCenter $ hBox + [ countdownBox + , currentTimeBox + , cosmicTimeBox + ]) + , + str "\n" + , + (borderWithLabel (str progressLabel) $ + updateAttrMap + (A.mapAttrName yDoneAttr P.progressCompleteAttr . + A.mapAttrName yToDoAttr P.progressIncompleteAttr) $ + progressBar Nothing (realToFrac $ yearElapsed // yearLength)) + ]) + <=> + str "\n" + <=> + hCenter (hBox [ + -- TODO: accumulate all entries on today's date into one vBox + if currentEntryIsCurrent then + (borderWithLabel (txt "Now on the Cosmic Calendar") currentEntry) <=> + (fromMaybe (str "") $ fmap (borderWithLabel (txt "Next on the Cosmic Calendar")) nextEntryShort) + else + borderWithLabel (txt "Next on the Cosmic Calendar") nextEntry, + -- vBox [ cosmicCalendarCurrent, txt "\n", cosmicCalendarNext ], + if showConversion + then + str " " <=> borderWithLabel (str "Cosmic Conversion") (hBox [cosmicConversion, cosmicConversion']) + else + str "" + ]) + where + -- TODO: We want to display "today" or "now" on the cosmic calendar; + -- We want to display what happened previously on the cosmic calendar + -- We want to say how long ago the previous happening was relative to today's date and today's place on the cosmic calendar + -- (E.g., if it's 1AM Jan 1, then we say the big bang was 1 hour ago and 1.6 million years ago) + -- We want to say similar for how long until the next happening + -- We also _may_ want to say the same thing for the current happening, depending on if it's an instant or a stage + -- If it's a stage, we want to say how long it lasts; how long since it started, and how long until it ends + + currentEntryIsCurrent = fromMaybe True $ do + (LocalTime entryDay _) <- (`addLocalTime` yearStart t) . calBeginTime <$> getCurrentCalendarEntry theCalendar t + let (LocalTime nowDay _) = t + return $ entryDay == nowDay + currentEntry = fromMaybe (str "none") $ calendarWidget False <$> getCurrentCalendarEntry theCalendar t + nextEntry = fromMaybe (str "none") $ calendarWidget False <$> getNextCalendarEntry theCalendar t + nextEntryShort = fmap (str "\n" <=>) (calendarWidget True <$> getNextCalendarEntry theCalendar t) + + calendarWidget short CalendarEntry{..} = box -- vBox [eventCountdown, str "\n", box] + where + timeUntilActive = (calBeginTime `addLocalTime` yearStart t) `diffLocalTime` t + eventCountdown = if timeUntilActive >= 0 then + hBox [str $ "in " ++ showTime timeUntilActive, + padLeft Max $ str $ "in " ++ showCosmicTime timeUntilActive] + else + hBox [str $ showTime (-timeUntilActive) ++ " ago", + padLeft Max $ str $ showCosmicTime (-timeUntilActive) ++ " ago"] + years = fromRational $ toCosmicTime calBeginTime + box = vBox [ + if currentEntryIsCurrent && not short + then str "\n" + else eventCountdown <=> str "\n", + hCenter $ txt calTitle, + hCenter $ txt calSubtitle, + str "\n", + hBox [ + let cosmicSecondsAgo = nominalDiffTimeToSeconds (yearEnd cosmicCalendarT `diffLocalTime` cosmicCalendarT) + cosmicCalendarT = calBeginTime `addLocalTime` yearStart t + in vBox [ + str $ formatTime defaultTimeLocale "%A, %B %e%n%Y-%m-%d %r" $ cosmicCalendarT, + -- TODO: Choose correct cosmic unit + str $ printf "%s cosmic second%s ago" (commasF' 1 cosmicSecondsAgo) (pluralize cosmicSecondsAgo) + ], + padLeft Max $ vBox [ + str $ showLarge years ++ " years", + str $ printf "%s years ago" $ showLarge $ realToFrac (ageOfUniverseInYears - floor years) + ] + ], + -- str $ printf "%s years ago" (commas $ ageOfUniverseInYears - floor years), + if not short + then + str "\n" <=> + txtWrap calDescription + else + str "" + ] + + strWhen b s = str $ if b then s else "" + countdownBox = + (borderWithLabel (str $ printf "Countdown %d" currentYear) $ + vBox $ + let secondsNow = 1 + toSeconds yearElapsed :: Int + secondsTotal = toSeconds yearLength + in + (str $ printf "Day %d of %d\nSecond %s of %s\n%s seconds remain" + dayNum + numDays + (commas secondsNow) + (commas secondsTotal) + (commas $ secondsTotal - secondsNow) + ) : remains + ) + remains = + [ + strWhen (hoursLeft >= 24) $ + printf "%d day%s remain%s" + daysLeft + (pluralize daysLeft) + (pluralizeVerb daysLeft), + + strWhen (hoursLeft < 24 && hoursLeft > 1) $ + printf "%s hour%s remain%s" + (commasF 2 hoursLeft) + (pluralize $ (floor hoursLeft :: Integer)) + (pluralizeVerb $ (floor hoursLeft :: Integer)), + + strWhen (hoursLeft <= 1 && minutesLeft > 1) $ + printf "%s minute%s remain%s" + (commasF 2 minutesLeft) + (pluralize $ (floor minutesLeft :: Integer)) + (pluralizeVerb $ (floor minutesLeft :: Integer)), + + strWhen (minutesLeft <= 1) $ + printf "%s second%s remain%s" + (commasF' 1 secondsLeft) + (pluralize secondsLeft) + (pluralizeVerb secondsLeft) + ] + + cosmicTimeBox = + (borderWithLabel (str "Cosmic Time") $ + vBox [(str $ printf "%s years" (commas $ (floor cosmicYears :: Integer))), + str "\n", + (str $ printf "%s years ago" (commas $ (floor cosmicYearsAgo :: Integer))) + -- , (str $ printf "%s years ago" (showLarge $ (realToFrac cosmicYearsAgo))) + -- , (str $ printf "%s billion years ago" (commasF 9 $ cosmicYearsAgo / (1000*1000*1000))) + -- , (str $ printf "%s million years ago" (commasF 6 $ cosmicYearsAgo / (1000*1000))) + -- , (str $ printf "%s thousand years ago" (commasF 3 $ cosmicYearsAgo / 1000)) + -- , (str $ printf "%s days ago" (commas $ (floor $ realToFrac cosmicYearsAgo * daysPerYear :: Integer))) + ]) + currentTimeBox = (hCenter (borderWithLabel (str $ printf "Current time%s" (if isSimulated then " (SIMULATED)" else "" :: String)) $ + padLeftRight 3 $ (str (formatTime defaultTimeLocale "%A, %B %e%n%Y-%m-%d %r" t)))) + cosmicYears = realToFrac ageOfUniverseInYears * (realToFrac $ (yearElapsed // yearLength)) :: Rational + cosmicYearsAgo = realToFrac ageOfUniverseInYears * (realToFrac $ 1 - (yearElapsed // yearLength)) :: Rational + -- cosmicYearsAgo = if yearElapsed == yearLength + -- then 0 + -- else realToFrac ageOfUniverseInYears * (realToFrac $ 1 - (yearElapsed // yearLength)) :: Rational + currentYear = yearNumber t + dayNum = dayNumOfYear t + numDays = daysInYear t + -- yearLength = fromIntegral numDays * nominalDay + yearLength = yearEnd t `diffLocalTime` yearStart t + yearElapsed = t `diffLocalTime` yearStart t + + daysLeft = numDays - dayNum + hoursLeft = minutesLeft / 60 + minutesLeft = fromRational $ toRational secondsLeft / 60 :: Double + toSeconds = floor . nominalDiffTimeToSeconds + secondsLeft = nominalDiffTimeToSeconds (yearLength - yearElapsed) + x // y = fromRational $ toRational x / toRational y :: Double + progressLabel = printf "%.6F%%" (100 * (yearElapsed // yearLength)) + +commasF' 1 n = if (floor (n * 10) `mod` 10 :: Int) == 0 then commasF 0 n `Text.append` " " else commasF 1 n +commasF' p n = commasF p n + +commasF', commasF :: RealFrac x => Int -> x -> Text +commasF precision = prettyF cfg + where + cfg = PrettyCfg precision (Just ',') '.' + +commas :: Integral i => i -> Text +commas = prettyI (Just ',') . fromIntegral + +nextTenthOfSecond :: ZonedTime -> ZonedTime +nextTenthOfSecond (ZonedTime (LocalTime day (TimeOfDay h m s)) z) = (ZonedTime (LocalTime day (TimeOfDay h m s')) z) + where + s' = fromRational $ toRational (floor (s * 10) + 1 :: Integer) / 10 + +nextWholeSecond :: ZonedTime -> ZonedTime +nextWholeSecond (ZonedTime (LocalTime day (TimeOfDay h m s)) z) = (ZonedTime (LocalTime day (TimeOfDay h m s')) z) + where + s' = fromIntegral $ (floor s + 1 :: Int) + +diffZonedTime :: ZonedTime -> ZonedTime -> NominalDiffTime +diffZonedTime = diffLocalTime `Prelude.on` zonedTimeToLocalTime + +isNewYearsEve :: LocalTime -> Bool +isNewYearsEve t = dayNumOfYear t == daysInYear t + +queueNextEvent :: MonadIO m => Bool -> BChan CustomEvent -> m ZonedTime +queueNextEvent hyper chan = liftIO $ do + now <- getZonedTime + void . forkIO $ do + + let getNext = if hyper then nextTenthOfSecond else nextWholeSecond + next = getNext now + delay = next `diffZonedTime` now + threadDelay $ floor $ delay * 1000 * 1000 + writeBChan chan $ TimeChanged next + return now + +isSimulatedTime :: St -> Bool +isSimulatedTime st = st ^. stDisplayTime /= st ^. stClockTime + +nextCalendarEntryTime :: LocalTime -> LocalTime +nextCalendarEntryTime t = fromMaybe t $ getNextCalendarEntry theCalendar t <&> (`addLocalTime` yearStart t) . calBeginTime + +previousCalendarEntryTime :: LocalTime -> LocalTime +previousCalendarEntryTime t = fromMaybe t $ goBack t + where + goBack t = getPreviousCalendarEntry theCalendar t <&> (`addLocalTime` yearStart t) . calBeginTime + +handleEvent :: BChan CustomEvent -> St -> BrickEvent () CustomEvent -> EventM () (Next St) +handleEvent chan st e = + case e of + VtyEvent (V.EvKey V.KEsc []) -> halt st + VtyEvent (V.EvKey (V.KChar 'p') []) -> cont $ st & stPaused %~ not + VtyEvent (V.EvKey (V.KFun 1) []) -> cont $ st & stPaused %~ not + + VtyEvent (V.EvKey V.KRight [MShift]) -> cont $ st & stDisplayTime %~ (addLocalTime (1)) + VtyEvent (V.EvKey V.KLeft [MShift]) -> cont $ st & stDisplayTime %~ (addLocalTime (-1)) + + VtyEvent (V.EvKey V.KRight [MCtrl]) -> cont $ st & stDisplayTime %~ (addLocalTime (60)) + VtyEvent (V.EvKey V.KLeft [MCtrl]) -> cont $ st & stDisplayTime %~ (addLocalTime (-60)) + + VtyEvent (V.EvKey V.KPageDown [MCtrl]) -> cont $ st & stDisplayTime %~ (addLocalTime (60 * 60)) + VtyEvent (V.EvKey V.KPageUp [MCtrl]) -> cont $ st & stDisplayTime %~ (addLocalTime (-60 * 60)) + VtyEvent (V.EvKey V.KPageDown []) -> cont $ st & stDisplayTime %~ (addLocalTime lengthOfDay) + VtyEvent (V.EvKey V.KPageUp []) -> cont $ st & stDisplayTime %~ (addLocalTime (-lengthOfDay)) + + VtyEvent (V.EvKey V.KHome []) -> cont $ st & stDisplayTime .~ (st ^. stClockTime) + VtyEvent (V.EvKey V.KHome [MShift]) -> cont $ st & stDisplayTime .~ (yearStart $ st ^. stClockTime) + VtyEvent (V.EvKey V.KEnd []) -> cont $ st & stDisplayTime .~ (newYearsEveLast10 $ st ^. stClockTime) + VtyEvent (V.EvKey V.KEnd [MShift]) -> cont $ st & stDisplayTime .~ (yearEnd $ st ^. stClockTime) + VtyEvent (V.EvKey V.KEnd [MCtrl]) -> cont $ st & stDisplayTime .~ (newYearsEveNoon $ st ^. stClockTime) + + VtyEvent (V.EvKey V.KRight []) -> cont $ st & stDisplayTime %~ nextCalendarEntryTime + VtyEvent (V.EvKey V.KLeft []) -> cont $ st & stDisplayTime %~ previousCalendarEntryTime + VtyEvent (V.EvKey (V.KChar '.') []) -> cont $ st & stDisplayTime %~ nextCalendarEntryTime + VtyEvent (V.EvKey (V.KChar ',') []) -> cont $ st & stDisplayTime %~ previousCalendarEntryTime + + VtyEvent (V.EvKey (V.KChar 'c') []) -> cont $ st & stShowConversion %~ not + VtyEvent (V.EvKey (V.KFun 2) []) -> cont $ st & stShowConversion %~ not + + VtyEvent _ -> cont st + AppEvent (TimeChanged now) -> do + let hyper = isNewYearsEve $ st ^. stDisplayTime + void $ queueNextEvent hyper chan + let oldTime = st ^. stClockTime + cont $ st & stClockTime .~ (zonedTimeToLocalTime now) + & stDisplayTime %~ if st ^. stPaused then id else addLocalTime $ zonedTimeToLocalTime now `diffLocalTime` oldTime + _ -> cont st + where + cont s = do + continue $ s & stLastBrickEvent .~ (Just e) + +newYearsEveLast10 :: LocalTime -> LocalTime +newYearsEveLast10 = addLocalTime (-11) . yearEnd + +newYearsEveNoon :: LocalTime -> LocalTime +newYearsEveNoon (LocalTime d (TimeOfDay _ _ s)) = LocalTime d' t + where + (y, _) = toOrdinalDate d + d' = fromOrdinalDate y 366 + t = TimeOfDay 12 0 s' + s' = s `mod'` 1 -- keep the fractional part so we still tick the display on the same schedule + +initialState :: LocalTime -> St +initialState t = + St { _stLastBrickEvent = Nothing + , _stClockTime = t + , _stDisplayTime = t + , _stNextEvent = Nothing + , _stPaused = False + , _stShowConversion = False + } + +daysInYear :: LocalTime -> Int +daysInYear (toGregorian . localDay -> (y, _, _)) = if isLeapYear y then 366 else 365 + +theBaseAttr :: A.AttrName +theBaseAttr = A.attrName "theBase" + +xDoneAttr, xToDoAttr :: A.AttrName +xDoneAttr = theBaseAttr <> A.attrName "X:done" +xToDoAttr = theBaseAttr <> A.attrName "X:remaining" + +yDoneAttr, yToDoAttr :: A.AttrName +yDoneAttr = theBaseAttr <> A.attrName "Y:done" +yToDoAttr = theBaseAttr <> A.attrName "Y:remaining" + +zDoneAttr, zToDoAttr :: A.AttrName +zDoneAttr = theBaseAttr <> A.attrName "Z:done" +zToDoAttr = theBaseAttr <> A.attrName "Z:remaining" + +theMap :: A.AttrMap +theMap = A.attrMap V.defAttr + [ (theBaseAttr, bg V.brightBlack) + , (xDoneAttr, V.black `on` V.white) + , (xToDoAttr, V.white `on` V.black) + , (yDoneAttr, V.magenta `on` V.yellow) + , (zDoneAttr, V.blue `on` V.green) + , (zToDoAttr, V.blue `on` V.red) + , (P.progressIncompleteAttr, fg V.yellow) + ] + +theApp :: BChan CustomEvent -> App St CustomEvent () +theApp chan = + App { appDraw = drawUI + , appChooseCursor = showFirstCursor + , appHandleEvent = handleEvent chan + , appStartEvent = return + , appAttrMap = const theMap + } + +main :: IO () +main = do + chan <- newBChan 10 + + let buildVty = V.mkVty V.defaultConfig + initialVty <- buildVty + now <- queueNextEvent False chan + void $ customMain initialVty buildVty (Just chan) (theApp chan) (initialState $ zonedTimeToLocalTime now) -- cgit v1.2.3