ic/tzo: add appendix
This commit is contained in:
parent
0f13ca785f
commit
1a5421d949
@ -28,7 +28,7 @@ However, there have been several moments in the history of science when research
|
||||
|
||||
<center>([Read more](/tbc/31/))</center>
|
||||
|
||||
# Inside links
|
||||
### Inside links
|
||||
|
||||
[i2] EPR and relativity, [https://kniganews.org/map/e/01-00/hex4a/](https://kniganews.org/map/e/01-00/hex4a/)
|
||||
|
||||
@ -36,7 +36,7 @@ However, there have been several moments in the history of science when research
|
||||
|
||||
[i4] Loops and networks, [https://kniganews.org/map/w/10-00/hex8c/](https://kniganews.org/map/w/10-00/hex8c/)
|
||||
|
||||
# Outside links
|
||||
### Outside links
|
||||
|
||||
[o4] Amir D. Aczel, "*Entanglement: the greatest mystery in physics*". Four Walls Eight Windows (2002); A. Bokulich and G. Jaeger (eds), "*Philosophy of Quantum Information and Entanglement*", Cambridge University Press (2010)
|
||||
|
||||
|
155
data/tzo/appendix.md
Normal file
155
data/tzo/appendix.md
Normal file
@ -0,0 +1,155 @@
|
||||
To make it clearer how the "**brief guide**" to the materials of the not-yet-complete "Book of NEWS" came about, it makes sense to include the article whose conclusion ultimately prompted the creation of the text "**beyond the clouds**".
|
||||
|
||||
# Missing Idea
|
||||
|
||||
<center>(November 2012)</center>
|
||||
|
||||

|
||||
|
||||
The large set of interconnected problems collectively known as the Langlands Program is sometimes also referred to as the “Grand Unified Theory of Mathematics.” In other words, for nearly half a century now, numerous scholars from around the world have been making very serious efforts toward a grand common goal.
|
||||
|
||||
Step by step, they manage to show that the vast world of mathematical research, once appearing as a collection of various and often unrelated territories, in fact, is structured in a fundamentally different way. That is, areas previously perceived as having nothing in common turn out to be equivalent descriptions of essentially the same structure.
|
||||
|
||||
A structure that is both extremely complex to master and – as many anticipate – elegantly simple and beautiful in its final picture. In short, a unified construction at the basis of all mathematics – surely lovely, but not yet comprehended by science.
|
||||
|
||||
And what's surprising is that in the vastness of the public encyclopedia "Wikipedia," where the number of articles in just one Russian-language section is approaching a million, there is practically no information about this in Russian.
|
||||
|
||||
That is, there is no article on the "Langlands Program" itself nor an article on Robert Langlands – the well-known Canadian mathematician who initiated this work back in the 1960s and celebrated his 76th birthday last October.
|
||||
|
||||
Such blatant indifference of society to major breakthroughs occurring at the forefront of theoretical science is, of course, characteristic not only for our country. This phenomenon, upon closer inspection, is currently virtually ubiquitous.
|
||||
|
||||
Scientists, of course, are seriously concerned about this trend. It was for this reason, actually, that the first international [Fields Medal Symposium](http://www.fields.utoronto.ca/programs/scientific/fieldsmedalsym/12-13/) was organized in October this year in Toronto, Canada, aimed at a wider popularization of mathematical science achievements among the masses.
|
||||
|
||||
From now on, this event is planned to be held annually by the Fields Institute, with each subsequent symposium – like the first one – focused on an area of mathematics where outstanding successes have been achieved by one of the recent Fields Medal laureates. (For those who might not be aware, the Fields Medal is considered a sort of "mathematical equivalent" of the Nobel Prize – the highest award among mathematicians, awarded every 4 years to scientists aged no more than 40.)
|
||||
|
||||
As for the thematic focus of the First Fields Symposium, it is of course no coincidence that it was dedicated to the "Fundamental Bases of the Langlands Program." And as the "main hero" of the forum, the first great mathematician of the Vietnamese people Ngô Bảo Châu was chosen, awarded the Fields Medal in 2008 for proving the Fundamental Lemma in the Langlands theory (an important but technically auxiliary assertion formulated back in 1983, which no one managed to prove for a quarter of a century; Ngô Bảo Châu not only proved the lemma in an unexpected and innovative way but also discovered many previously unknown interrelations).
|
||||
|
||||
To better understand why this is indeed important not only for narrowly specialized theorists deeply immersed in their mathematical abstractions but also for humanity as a whole, it is best to give the floor to a specialist. Someone who not only understands the subject in detail but can also clearly explain the essence of discoveries to ordinary people far from mathematics.
|
||||
|
||||
In this case, [Edward Frenkel](http://math.berkeley.edu/~frenkel/), a professor of mathematics at the University of California, Berkeley, and one of the main scientific organizers of the first Fields Medal Symposium, is an almost perfect fit. In a large interview preceding the event, Frenkel gave a popular overview of the Langlands Program, its general history, and current features.
|
||||
|
||||
The full original of this interview can be found [on the University of Toronto website](http://blog.fields.utoronto.ca/symposium/2012/09/05/the-geometric-langlands-program-with-edward-frenkel/), but in a brief free retelling, Frenkel's theses look something like this.
|
||||
|
||||
<center># What Professor Frenkel Said</center>
|
||||
|
||||
The research being conducted within the Langlands Program is often characterized as a strict development of mathematical language establishing correspondence between number theory and mathematical analysis. While this can be said, in reality, it is much more.
|
||||
|
||||
When Robert Langlands began his Program at the end of the 1960s, the main impetus driving him towards these inquiries was rather difficult questions in number theory.
|
||||
|
||||
In this field, one often deals with solutions to algebraic power equations (like, say, *y*<sup>2</sup> = *x*<sup>3</sup> + 5*x* +3), with the characteristic that all calculations here are conducted only over integers "modulo ***p***". The principles of modular arithmetic are easiest explained with a clock face, where no matter how much time passes, the hands' positions are always given "modulo 12" (though, with a more rigorous approach, the dial should show numbers from 0 to 11, but these are technical nuances).
|
||||
|
||||
In number theory, for several fundamental reasons, situations where number sets defining a multitude of equation values are formed by such moduli ***p***, which are prime numbers (divisible only by themselves and 1), are particularly important. Under these conditions, when faced with a particular equation, it is extremely desirable to know in advance how many solutions the given equation has – for all possible values of the prime modulo*** p***. It turns out that this is an extremely difficult question.
|
||||
|
||||
Langlands' deep and unexpected insight was that unknown numbers of solutions, as it turned out, could be read off objects in an entirely different area of mathematics, called "harmonic analysis."
|
||||
|
||||
This section of mathematical analysis studies special kinds of functions – those directly related to regular oscillations and music, hence named harmonic. For a simple example, everyone knows basic trigonometric functions like sin(*x*) and cos(*x*). To this elementary series also belong functions sin(*nx*) and cos(*nx*) for all integer values of *n*.
|
||||
|
||||
According to results obtained by Jean-Baptiste Fourier at the beginning of the 19th century, almost all functions that are periodic can be equivalently written in the form of a "superposition" or composition of these basic simple functions. This is a very strong and, as life has shown, extremely useful statement!
|
||||
|
||||
In communications, for instance, imagine having a signal represented by a function. Transforming it into a sum of simple trigonometric functions is a decomposition of the signal into "elementary harmonics" (which can be processed systematically far more easily).
|
||||
|
||||
This, essentially, is the essence of harmonic analysis: finding some elementary harmonics, like sin(*nx*) and cos(*nx*), but only in a far more general situation, and finding ways to decompose arbitrary functions in terms of such harmonics.
|
||||
|
||||
This remarkable theory nowadays finds a plethora of useful applications. Nonetheless, it must be emphasized that at first glance, it seemed exceedingly distant from number theory.
|
||||
|
||||
Then came the surprise. Robert Langlands conjectured and demonstrated in broad strokes that **these two worlds – number theory and harmonic analysis – are inextricably linked**.
|
||||
|
||||
To put it more accurately, he conjectured that questions in number theory, such as finding the number of solutions to equations modulo a prime, could be solved using the apparatus of harmonic analysis.
|
||||
|
||||
For every equation, like the one given above, there exists a harmonic function that somehow already "knows" everything about the number of solutions to this equation modulo all the primes (thus allowing them to be calculated quite simply).
|
||||
|
||||
Since this mutual correspondence didn’t follow from anywhere, the discovery seemed extremely puzzling – like some sort of magic and wizardry…
|
||||
|
||||
This is why the mathematical world was so excited about the Langlands program. Primarily because developing this direction gives us a way to solve tasks that previously seemed insoluble problems.
|
||||
|
||||
There is also a second, equally important aspect. The Langlands program points to some very deep and fundamental connections between various fields of mathematics.
|
||||
|
||||
Naturally, one is eager to know what is really happening here. Why are these things linked in this way? **But we still don't fully understand this…**
|
||||
|
||||
This is approximately how the Langlands program began.
|
||||
|
||||
After that, **the same mysterious patterns and correspondences began gradually emerging not only in other areas of mathematics like geometry but also in quantum physics.**
|
||||
|
||||
The Langlands program is sometimes called the **Grand Unified Theory of Mathematics**. This program points to some universal phenomena and interconnections between these phenomena, encompassing very different areas of mathematics. Perhaps here lie the keys to understanding what mathematics represents in general…
|
||||
|
||||
To date, the Langlands program is a vast area of research. As the ideas of the program have spread in many directions, there is now a large community of specialists from quite diverse fields of mathematics and theoretical physics working here.
|
||||
|
||||
The situation seems as if you have numerous entirely different languages and sets of sentences from these different languages, which you already know signify the same thing. So you lay these sentences side by side and gradually begin developing a dictionary that allows you to translate the same substantive statements, but only formulated in different areas of mathematics, in quantum field theory, or string theory.
|
||||
|
||||
Work on the Langlands Program, of course, will continue. At the end of the interview, Edward Frenkel put it this way:
|
||||
|
||||
> The more we know, the more we understand how little we know. As I said, the beauty of the Langlands Program is that it points to **mysterious connections** between different fields of mathematics.
|
||||
>
|
||||
> And the biggest question, in my mind, is ***why*** these connections exist, what is the mechanism behind them. We still don’t know, but we are working on it.
|
||||
>
|
||||
> Now we understand better how different pieces of the puzzle fit together.
|
||||
>
|
||||
> But we need **new, fresh ideas**.
|
||||
|
||||
And while new fresh ideas have not yet appeared on the horizon, it might be worth taking a closer look around. And consider ideas that are quite old, but still not properly developed.
|
||||
|
||||
<center># Two Mysteries or One?</center>
|
||||
|
||||
Among the vast number of mysteries of nature still unresolved by humans, two secrets particularly impress with their scale and, therefore, are remembered more often than others.
|
||||
|
||||
The first mystery, the most discomforting: what is it, dark matter and dark energy, accounting for 96% of the universe?
|
||||
|
||||
The pinnacle of modern scientific knowledge about the nature of the universe, the Standard Model of physics, describes the observable world in terms of quarks, leptons, and other quantum particle-fields that transmit interactions. However, it must be admitted that all these things constitute only 4% of the entire mass-energy of the universe.
|
||||
|
||||
Science knows nothing and cannot say anything about the remaining 96%, except calling the unknown "dark matter" and "dark energy."
|
||||
|
||||
***The second mystery is the enigma of "the unreasonable effectiveness of mathematics"*** (as Eugene Wigner phrased it).
|
||||
|
||||
Throughout the history of science, theoreticians repeatedly confront situations where the mathematical equations they derive to describe physical laws actually "know" more than the discoverers themselves.
|
||||
|
||||
A typical example. When, for instance, Albert Einstein completed the development of his general theory of relativity in 1916, pondering over the derived equations, he suddenly noticed an entirely unexpected message, which stated that the universe was expanding.
|
||||
|
||||
Einstein, at that time, was convinced in a stationary and unchanging worldview, so he did not believe that the physical universe could contract or grow in size. In other words, he ignored what the equations were telling him. Thirteen years later, Edwin Hubble's astronomical observations convincingly demonstrated evidence of the universe's expansion. Thus, Einstein missed the opportunity to make one of the most striking and unexpected scientific predictions in history.
|
||||
|
||||
Naturally arises an intriguing question: how did Einstein's equations "know" that the universe was expanding when he did not know it and did not wish to know?
|
||||
|
||||
And if mathematics, as some believe, is just a language invented and used by humans to describe the world (i.e. an invention of the human brain), how can it give rise to something that is clearly beyond what people input into it?
|
||||
|
||||
Whenever mathematical equations themselves "know" and provide scientists with predictions about undiscovered particles or any other properties of physical reality, one involuntarily thinks of a peculiar idea: "Maybe it’s because math ***is*** reality" (using an expression by Brian Greene, a known popularizer of string theory and professor of physics at Columbia University).
|
||||
|
||||
But from here emerges another big question: why then is the universe made of only a small part of all the mathematics available to humanity?
|
||||
|
||||
Once again quoting Brian Greene: "There’s a lot of math out there. Today only a tiny sliver of it has a realisation in the physical world. Pull any math book off the shelf and most of the equations in it don’t correspond to any physical object or physical process" …
|
||||
|
||||
Another appropriate quote from some famous scientific luminary is not at hand, but the next logical idea practically lies on the surface. And therefore, surely, some authority has already voiced it (and even if not, it changes nothing):
|
||||
|
||||
> If the world observed by humans constitutes only a tiny 4% of everything that exists in the universe, and of the immense complex of mathematics already mastered by humans, only a tiny fraction corresponds to the description of the observable reality, then perhaps the answer to the two great mysteries of nature has already been found?
|
||||
>
|
||||
> That is, it is not excluded that mathematicians and theoretical physicists, long and thoroughly studying abstract worlds, sometimes or even wholly distant from reality, are indeed exploring those very 96% invisible to human eyes…
|
||||
|
||||
There is currently no way to prove such a hypothesis. However, to support it, it is useful to recall one more, third, great mystery, without which the overall picture "makes no sense" – in the literal understanding of these words.
|
||||
|
||||
<center># What Professor Penrose Drew</center>
|
||||
|
||||
In 2004, a voluminous monograph by the famous British physicist and mathematician Roger Penrose was published: "*The Road to Reality. A Complete Guide to the Laws of the Universe.*"
|
||||
|
||||
So, in this book, an entire separate subsection (1.4) is dedicated to another great mystery – the incomprehensible position occupied by human consciousness between physical reality and the mathematical world.
|
||||
|
||||
Penrose refers to this complex as "three worlds or three forms of existence": the form of physical existence, the form of mental existence, and the form of mathematical existence (the Platonic world of ideas). It is clear that all these forms are closely connected to each other, "with the corresponding relationships being as fundamental as they are mysterious" (quoting the author).
|
||||
|
||||
Using this illustration, Penrose schematically depicted all these three forms of existence in the form of spheres, representing objects belonging to three different worlds. Here is also shown the essence of the mysterious relationships between these worlds.
|
||||
|
||||

|
||||
|
||||
The essence of the mysteries is quite clear. As noted earlier, if we consider the sphere of mathematics, only a very small part of the mathematical world directly relates to processes of the physical world.
|
||||
|
||||
Similarly, in the realm of the physical world (as it is known by modern science), only a very, very small part relates to consciousness and is linked with the phenomenon of mental activity.
|
||||
|
||||
And finally, the third connection-mystery, linking consciousness with the mathematical sphere, is also quite obvious: human reflections about absolute mathematical truths constitute an extremely small portion of our total cognitive activity.
|
||||
|
||||
In the end, from these quite apparent relationships, a clear paradox emerges – where each world contains as a small fragment the entire next world in its entirety. But the chain of interconnections is closed…
|
||||
|
||||
The author openly admits his inability to solve this trifecta puzzle. But, he adds, instead of a solution one can present the existence of another, even more enigmatic idea-mystery, surpassing and encompassing all those already mentioned:
|
||||
|
||||
> There may be a sense in which the three worlds are not separate at all, but merely reflect, individually, aspects of a **deeper truth about the world as a whole** of which we have little conception at the present time.
|
||||
|
||||
This, let us emphasize, is how the well-known scientist Roger Penrose views the situation.
|
||||
|
||||
However, there are other well-known scientists who have quite definite ideas and conceptions on the matter. And most pleasantly, these different ideas blend quite well together.
|
||||
|
||||
But this is already a topic for another text.
|
@ -136,4 +136,9 @@ part_7:
|
||||
afraid”…"
|
||||
- "Aliens and resolving the “Fermi paradox”; Cameron’s “Avatar” and Thoth-Djehuti of ancient Egyptians; Egyptian
|
||||
“Book of the Dead” and its Chapter 64 on comprehending all chapters of ascending to light in one chapter; Pauli,
|
||||
Jung, and the arrival of aliens “from within our consciousness”; Peace as the universe in our hands and the simplest recipe for awakening."
|
||||
Jung, and the arrival of aliens “from within our consciousness”; Peace as the universe in our hands and the simplest recipe for awakening."
|
||||
appendix:
|
||||
label: Appendix
|
||||
# full_title: "Appendix: Missing Idea"
|
||||
toc:
|
||||
- "Missing Idea."
|
BIN
public/ic/images/tzo/3worlds.jpg
Normal file
BIN
public/ic/images/tzo/3worlds.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 32 KiB |
BIN
public/ic/images/tzo/birds.jpg
Normal file
BIN
public/ic/images/tzo/birds.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 66 KiB |
BIN
public/ic/images/tzo/equ123.jpg
Normal file
BIN
public/ic/images/tzo/equ123.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 19 KiB |
@ -17,7 +17,7 @@ class MainHandler
|
||||
|
||||
$this->skin->options->isIndex = true;
|
||||
$this->skin->set([
|
||||
'tzo' => new TZO()
|
||||
'parts' => TZO::getParts()
|
||||
]);
|
||||
|
||||
return $this->skin->renderPage('index.twig');
|
||||
@ -32,37 +32,48 @@ class MainHandler
|
||||
}
|
||||
|
||||
public function GET_tzo() {
|
||||
$tzo = new TZO();
|
||||
$this->skin->set([
|
||||
'tzo' => $tzo,
|
||||
'strings' => $tzo->strings
|
||||
'parts' => TZO::getParts(),
|
||||
'appendix' => new TZOPart(appendix: true)
|
||||
]);
|
||||
$this->skin->options->headSection = 'tbc';
|
||||
return $this->skin->renderPage('tzo.twig');
|
||||
}
|
||||
|
||||
public function GET_tzo_part() {
|
||||
list($part) = $this->input('i:part');
|
||||
list($part) = $this->input('part');
|
||||
$tzo = new TZO();
|
||||
if (!$tzo->isPartValid($part))
|
||||
|
||||
switch ($part) {
|
||||
case 'appendix':
|
||||
$is_appendix = true;
|
||||
$part = null;
|
||||
break;
|
||||
default:
|
||||
$is_appendix = false;
|
||||
break;
|
||||
}
|
||||
try {
|
||||
$tzo_part = new TZOPart($part, $is_appendix);
|
||||
} catch (\ValueError $e) {
|
||||
throw new NotFound();
|
||||
$title = $tzo->getPartWithDots($part).'_'.$tzo->strings['part_'.$part]['label'];
|
||||
$html = $tzo->getPartHtml($part);
|
||||
}
|
||||
|
||||
$title = $tzo_part->getFullLabel();
|
||||
$html = $tzo_part->getHtml();
|
||||
|
||||
$this->skin->meta->title = $title.' - '.lang('tzo');
|
||||
$this->skin->meta->description = TZO::getDescriptionPreviewFromHtml($html, 155);
|
||||
$this->skin->meta->url = 'https://'.$_SERVER['HTTP_HOST'].'/tbc/'.$part.'/';
|
||||
$image = TZO::getFirstImageUrlFromHtml($html);
|
||||
$this->skin->meta->description = $tzo_part->getDescriptionPreview(155);
|
||||
$this->skin->meta->url = $tzo_part->getUrl();
|
||||
$image = $tzo_part->getFirstImageUrl();
|
||||
if ($image)
|
||||
$this->skin->meta->image = 'https://'.$_SERVER['HTTP_HOST'].$image;
|
||||
$this->skin->meta->image = $image;
|
||||
|
||||
$this->skin->title = $title.' - '.lang('tzo');
|
||||
$this->skin->set([
|
||||
'tzo' => $tzo,
|
||||
'part' => $part,
|
||||
'title' => $title,
|
||||
'html' => $html,
|
||||
'nav_html' => $tzo->getPartNavigationTree($part)
|
||||
'nav_html' => $tzo_part->getNavigationTreeHtml()
|
||||
]);
|
||||
return $this->skin->renderPage('tzo_part.twig');
|
||||
}
|
||||
|
@ -2,146 +2,21 @@
|
||||
|
||||
namespace app\ic;
|
||||
|
||||
use app\MarkupUtil;
|
||||
|
||||
class TZO
|
||||
{
|
||||
const array PARTS = [1, 21, 22, 31, 32, 33, 41, 42, 43, 44, 51, 52, 53, 61, 62, 7];
|
||||
|
||||
public readonly array $strings;
|
||||
|
||||
public function __construct() {
|
||||
$this->strings = yaml_parse_file(APP_ROOT.'/data/tzo/info.yaml');
|
||||
public static function getStrings(): array {
|
||||
static $strings;
|
||||
if ($strings === null)
|
||||
$strings = yaml_parse_file(APP_ROOT.'/data/tzo/info.yaml');
|
||||
return $strings;
|
||||
}
|
||||
|
||||
public function isPartValid(int $n): bool {
|
||||
return isset($this->strings['part_'.$n]);
|
||||
}
|
||||
|
||||
public function getPartLabel(int $n): string {
|
||||
return $this->strings['part_'.$n]['label'];
|
||||
}
|
||||
|
||||
public function getParts(): array {
|
||||
return static::PARTS;
|
||||
}
|
||||
|
||||
public function getPartWithDots(int $n): string {
|
||||
return implode('.', str_split((string)$n));
|
||||
}
|
||||
|
||||
public function getPartHtml(int $n): string {
|
||||
$markdown_file = APP_ROOT.'/data/tzo/'.$n.'.md';
|
||||
$md = file_get_contents($markdown_file);
|
||||
|
||||
// images
|
||||
$md = preg_replace_callback(
|
||||
'#!\[]\('
|
||||
// 1 = filename
|
||||
. '(/images/tzo/[\w\d\-.]+)'
|
||||
// 2 = caption
|
||||
. '(?:\s+"((?:\\\\.|[^"\\\\])*)")?'
|
||||
. '\)#',
|
||||
function($m) {
|
||||
$file = $m[1];
|
||||
$name = basename($file);
|
||||
$caption = isset($m[2]) ? stripcslashes($m[2]) : '';
|
||||
$path = APP_ROOT.'/public/ic/images/tzo/'.$file;
|
||||
list($w, $h) = $this->getImageSize($path); // TODO cache image size
|
||||
return (
|
||||
'<figure>'
|
||||
.'<div class="img-wrapper"><img src="'.htmlescape($file).'" width="'.$w.'" height="'.$h.'" alt="'.substr($name, strrpos($name, '.')+1).'"></div>'
|
||||
.($caption != '' ? '<figcaption>'.htmlescape($caption).'</figcaption>' : '')
|
||||
.'</figure>'
|
||||
);
|
||||
},
|
||||
$md
|
||||
);
|
||||
|
||||
$html = MarkupUtil::markdownToHtml($md,
|
||||
use_image_previews: false);
|
||||
|
||||
// links
|
||||
$html = preg_replace_callback(
|
||||
'/<center>\s*\(\[([^]]+)\]\(([^)]+)\)\)\s*<\/center>/',
|
||||
function ($matches) {
|
||||
$linkText = $matches[1];
|
||||
$url = $matches[2];
|
||||
return '<center>(<a href="'.htmlescape($url).'">'.htmlescape($linkText).'</a>)</center>';
|
||||
},
|
||||
$html
|
||||
);
|
||||
|
||||
// chapter markers
|
||||
$html = preg_replace_callback(
|
||||
'/<center>\((\d+)\)<\/center>/',
|
||||
function ($matches) {
|
||||
$number = $matches[1];
|
||||
return '<p class="tzo-chapter" id="chapter'.$number.'">('.$number.')</p>';
|
||||
},
|
||||
$html
|
||||
);
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
public static function getDescriptionPreviewFromHtml(string $html, int $len): string {
|
||||
$text = trim(MarkupUtil::htmlToText($html));
|
||||
if (mb_strlen($text) >= $len)
|
||||
return mb_substr($text, 0, $len - 3).'...';
|
||||
return $text;
|
||||
}
|
||||
|
||||
public static function getFirstImageUrlFromHtml(string $html): ?string {
|
||||
if (preg_match('/<img[^>]+src=[\'"]([^\'"]+)[\'"]/i', $html, $m))
|
||||
return $m[1];
|
||||
return null;
|
||||
}
|
||||
|
||||
protected function getImageSize(string $local_path): array {
|
||||
list($w, $h) = getimagesize($local_path);
|
||||
return [$w, $h];
|
||||
}
|
||||
|
||||
public function getPartNavigationTree(int $part): string {
|
||||
if ($part == 1)
|
||||
return '';
|
||||
|
||||
$buf_last_line = [];
|
||||
$buf_all_lines = [];
|
||||
|
||||
$part_row = intval($part > 10 ? floor($part / 10) : $part);
|
||||
$part_column = ($part < 10 ? $part*10 : $part) % 10;
|
||||
if ($part_column == 0)
|
||||
$part_column = 1;
|
||||
|
||||
for ($cur_row = 1;
|
||||
$cur_row <= $part_row;
|
||||
$cur_row++)
|
||||
{
|
||||
$columns = 4 - abs($cur_row - 4);
|
||||
for ($cur_column = 1; $cur_column <= $columns; $cur_column++) {
|
||||
$cur_part = $cur_row;
|
||||
if ($columns > 1) {
|
||||
$cur_part *= 10;
|
||||
$cur_part += $cur_column;
|
||||
}
|
||||
$label = $this->getPartLabel($cur_part);
|
||||
if ($cur_row == $part_row && $cur_column > $part_column) {
|
||||
$label_len = strlen($label);
|
||||
$label = $label[0].str_repeat('_', $label_len-1);
|
||||
}
|
||||
$cur_part_label = $this->getPartWithDots($cur_part).'_'.$label;
|
||||
if ($cur_row < $part_row || $cur_column < $part_column) {
|
||||
$buf_last_line[] = '<a href="/tbc/'.$cur_part.'/">'.htmlescape($cur_part_label).'</a>';
|
||||
} else {
|
||||
$buf_last_line[] = $cur_part_label;
|
||||
}
|
||||
}
|
||||
$buf_all_lines[] = implode(' <span>|</span> ', $buf_last_line);
|
||||
$buf_last_line = [];
|
||||
}
|
||||
|
||||
return implode('<br>', $buf_all_lines);
|
||||
/**
|
||||
* @return TZOPart[]
|
||||
*/
|
||||
public static function getParts(): array {
|
||||
return array_map(fn(int $n) => new TZOPart($n), self::PARTS);
|
||||
}
|
||||
}
|
178
src/lib/ic/TZOPart.php
Normal file
178
src/lib/ic/TZOPart.php
Normal file
@ -0,0 +1,178 @@
|
||||
<?php
|
||||
|
||||
namespace app\ic;
|
||||
|
||||
use app\MarkupUtil;
|
||||
|
||||
class TZOPart
|
||||
{
|
||||
protected ?string $html = null;
|
||||
|
||||
public function __construct(
|
||||
public readonly ?int $part = null,
|
||||
public readonly bool $appendix = false
|
||||
) {
|
||||
if (!$this->appendix) {
|
||||
if (!$this->part)
|
||||
throw new \ValueError("must be either appendix or valid part");
|
||||
if (!isset(TZO::getStrings()['part_'.$this->part]))
|
||||
throw new \ValueError("invalid part");
|
||||
}
|
||||
}
|
||||
|
||||
public function getNumberWithDots(): string {
|
||||
return $this->appendix ? 'null.error' : self::getPartNumberWithDots($this->part);
|
||||
}
|
||||
|
||||
protected static function getPartNumberWithDots(int $part): string {
|
||||
return implode('.', str_split((string)$part));
|
||||
}
|
||||
|
||||
public function getLabel(): string {
|
||||
return TZO::getStrings()[$this->getStringsKey()]['label'];
|
||||
}
|
||||
|
||||
protected function getStringsKey(): string {
|
||||
return self::getPartStringsKey($this->part, $this->appendix);
|
||||
}
|
||||
|
||||
protected static function getPartStringsKey(?int $part, bool $appendix = false): string {
|
||||
return !$appendix ? 'part_'.$part : 'appendix';
|
||||
}
|
||||
|
||||
protected static function getPartLabel(int $part): string {
|
||||
return TZO::getStrings()[self::getPartStringsKey($part)]['label'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getTableOfContents(): array {
|
||||
return TZO::getStrings()[$this->getStringsKey()]['toc'];
|
||||
}
|
||||
|
||||
public function getFullLabel(): string {
|
||||
return TZO::getStrings()[$this->getStringsKey()]['full_title'] ?? (!$this->appendix ? $this->getNumberWithDots().'_' : '').$this->getLabel();
|
||||
}
|
||||
|
||||
public function getUrl(): string {
|
||||
return 'https://'.$_SERVER['HTTP_HOST'].'/tbc/'.($this->appendix ? 'appendix' : $this->part).'/';
|
||||
}
|
||||
|
||||
public function getHtml(): string {
|
||||
if ($this->html !== null)
|
||||
return $this->html;
|
||||
|
||||
$markdown_file = APP_ROOT.'/data/tzo/'.($this->appendix ? 'appendix' : $this->part).'.md';
|
||||
$md = file_get_contents($markdown_file);
|
||||
|
||||
// images
|
||||
$md = preg_replace_callback(
|
||||
'#!\[]\('
|
||||
// 1 = filename
|
||||
. '(/images/tzo/[\w\d\-.]+)'
|
||||
// 2 = caption
|
||||
. '(?:\s+"((?:\\\\.|[^"\\\\])*)")?'
|
||||
. '\)#',
|
||||
function($m) {
|
||||
$file = $m[1];
|
||||
$name = basename($file);
|
||||
$caption = isset($m[2]) ? stripcslashes($m[2]) : '';
|
||||
$path = APP_ROOT.'/public/ic'.$file;
|
||||
list($w, $h) = getimagesize($path); // TODO cache image size
|
||||
return (
|
||||
'<figure>'
|
||||
.'<div class="img-wrapper"><img src="'.htmlescape($file).'" width="'.$w.'" height="'.$h.'" alt="'.substr($name, 0, strrpos($name, '.')).'"></div>'
|
||||
.($caption != '' ? '<figcaption>'.htmlescape($caption).'</figcaption>' : '')
|
||||
.'</figure>'
|
||||
);
|
||||
},
|
||||
$md
|
||||
);
|
||||
|
||||
$html = MarkupUtil::markdownToHtml($md,
|
||||
use_image_previews: false);
|
||||
|
||||
// links
|
||||
$html = preg_replace_callback(
|
||||
'/<center>\s*\(\[([^]]+)]\(([^)]+)\)\)\s*<\/center>/',
|
||||
function ($matches) {
|
||||
$linkText = $matches[1];
|
||||
$url = $matches[2];
|
||||
return '<p style="text-align: center">(<a href="'.htmlescape($url).'">'.htmlescape($linkText).'</a>)</p>';
|
||||
},
|
||||
$html
|
||||
);
|
||||
|
||||
// chapter markers
|
||||
$html = preg_replace_callback(
|
||||
'/<center>(?:# )?(\(\d+\)|([\w\s?]+))<\/center>/',
|
||||
function ($matches) {
|
||||
$number = $matches[1];
|
||||
return '<p class="tzo-chapter" id="chapter'.$number.'">'.$number.'</p>';
|
||||
},
|
||||
$html
|
||||
);
|
||||
|
||||
$this->html = $html;
|
||||
return $html;
|
||||
}
|
||||
|
||||
public function getDescriptionPreview(int $len): string {
|
||||
$text = trim(MarkupUtil::htmlToText($this->getHtml()));
|
||||
if (mb_strlen($text) >= $len)
|
||||
return mb_substr($text, 0, $len - 3).'...';
|
||||
return $text;
|
||||
}
|
||||
|
||||
public function getFirstImageUrl(): ?string {
|
||||
if (!preg_match('/<img[^>]+src=[\'"]([^\'"]+)[\'"]/i', $this->getHtml(), $m))
|
||||
return null;
|
||||
$url = $m[1];
|
||||
if (!str_starts_with($url, 'https://'))
|
||||
$url = 'https://'.$_SERVER['HTTP_HOST'].$url;
|
||||
return $url;
|
||||
}
|
||||
|
||||
public function getNavigationTreeHtml(): string {
|
||||
if ($this->part == 1 || $this->appendix)
|
||||
return '';
|
||||
|
||||
$buf_last_line = [];
|
||||
$buf_all_lines = [];
|
||||
|
||||
$part_row = intval($this->part > 10 ? floor($this->part / 10) : $this->part);
|
||||
$part_column = ($this->part < 10 ? $this->part*10 : $this->part) % 10;
|
||||
if ($part_column == 0)
|
||||
$part_column = 1;
|
||||
|
||||
for ($cur_row = 1;
|
||||
$cur_row <= $part_row;
|
||||
$cur_row++)
|
||||
{
|
||||
$columns = 4 - abs($cur_row - 4);
|
||||
for ($cur_column = 1; $cur_column <= $columns; $cur_column++) {
|
||||
$cur_part = $cur_row;
|
||||
if ($columns > 1) {
|
||||
$cur_part *= 10;
|
||||
$cur_part += $cur_column;
|
||||
}
|
||||
$label = self::getPartLabel($cur_part);
|
||||
if ($cur_row == $part_row && $cur_column > $part_column) {
|
||||
$label_len = strlen($label);
|
||||
$label = $label[0].str_repeat('_', $label_len-1);
|
||||
}
|
||||
$cur_part_label = self::getPartNumberWithDots($cur_part).'_'.$label;
|
||||
if ($cur_row < $part_row || $cur_column < $part_column) {
|
||||
$buf_last_line[] = '<a href="/tbc/'.$cur_part.'/">'.htmlescape($cur_part_label).'</a>';
|
||||
} else {
|
||||
$buf_last_line[] = $cur_part_label;
|
||||
}
|
||||
}
|
||||
$buf_all_lines[] = implode(' <span>|</span> ', $buf_last_line);
|
||||
$buf_last_line = [];
|
||||
}
|
||||
|
||||
return implode('<br>', $buf_all_lines);
|
||||
}
|
||||
}
|
@ -59,7 +59,7 @@ return [
|
||||
'/' => 'index',
|
||||
'tbc/' => 'tzo',
|
||||
'{works}/' => 'books',
|
||||
'tbc/(\d+)/' => 'tzo_part part=$(1)'
|
||||
'tbc/(\d+|appendix)/' => 'tzo_part part=$(1)',
|
||||
],
|
||||
];
|
||||
})()
|
||||
|
@ -3,40 +3,37 @@
|
||||
<div class="index-title"><a href="/tbc/">{{ "tzo"|lang }}</a></div>
|
||||
<div class="index-subtitle">({{ "tzo_brief_guide"|lang|lower }})</div>
|
||||
<div class="tzo-map">
|
||||
{% for part in tzo.getParts() %}
|
||||
<a href="/tbc/{{ part }}/" class="node" id="n{{ part }}">
|
||||
<div class="node-number">{{ tzo.getPartWithDots(part) }}</div>
|
||||
<div class="node-label">{{ tzo.getPartLabel(part) }}</div>
|
||||
{% for part in parts %}
|
||||
<a href="/tbc/{{ part.part }}/" class="node" id="n{{ part.part }}">
|
||||
<div class="node-number">{{ part.getNumberWithDots() }}</div>
|
||||
<div class="node-label">{{ part.getLabel() }}</div>
|
||||
</a>
|
||||
{% endfor %}
|
||||
<div class="arrow a1-21 dir135"></div>
|
||||
<div class="arrow a1-22 dir45" ></div>
|
||||
<div class="arrow a1-22 dir45"></div>
|
||||
<div class="arrow a21-31 dir135"></div>
|
||||
<div class="arrow a21-32 dir45" ></div>
|
||||
<div class="arrow a21-32 dir45"></div>
|
||||
<div class="arrow a22-32 dir135"></div>
|
||||
<div class="arrow a22-33 dir45" ></div>
|
||||
<div class="arrow a22-33 dir45"></div>
|
||||
<div class="arrow a31-41 dir135"></div>
|
||||
<div class="arrow a31-42 dir45" ></div>
|
||||
<div class="arrow a31-42 dir45"></div>
|
||||
<div class="arrow a32-42 dir135"></div>
|
||||
<div class="arrow a32-43 dir45" ></div>
|
||||
<div class="arrow a32-43 dir45"></div>
|
||||
<div class="arrow a33-43 dir135"></div>
|
||||
<div class="arrow a33-44 dir45" ></div>
|
||||
<div class="arrow a41-51 dir45" ></div>
|
||||
<div class="arrow a33-44 dir45"></div>
|
||||
<div class="arrow a41-51 dir45"></div>
|
||||
<div class="arrow a42-51 dir135"></div>
|
||||
<div class="arrow a42-52 dir45" ></div>
|
||||
<div class="arrow a42-52 dir45"></div>
|
||||
<div class="arrow a43-52 dir135"></div>
|
||||
<div class="arrow a43-53 dir45" ></div>
|
||||
<div class="arrow a43-53 dir45"></div>
|
||||
<div class="arrow a44-53 dir135"></div>
|
||||
<div class="arrow a51-61 dir45" ></div>
|
||||
<div class="arrow a51-61 dir45"></div>
|
||||
<div class="arrow a52-61 dir135"></div>
|
||||
<div class="arrow a52-62 dir45" ></div>
|
||||
<div class="arrow a52-62 dir45"></div>
|
||||
<div class="arrow a53-62 dir135"></div>
|
||||
<div class="arrow a61-7 dir45" ></div>
|
||||
<div class="arrow a62-7 dir135"></div>
|
||||
<div class="arrow a61-7 dir45"></div>
|
||||
<div class="arrow a62-7 dir135"></div>
|
||||
</div>
|
||||
|
||||
{# <div class="index-hr">~ ~ ~</div>#}
|
||||
|
||||
<div class="index-more">
|
||||
More works <a href="/works/">here</a>
|
||||
</div>
|
||||
|
@ -2,16 +2,19 @@
|
||||
<h2>{{ "tzo_full_title"|lang }}</h2>
|
||||
|
||||
{% set chapter_number = 1 %}
|
||||
{% for part in tzo.getParts() %}
|
||||
{% for part in parts %}
|
||||
<h3>
|
||||
<a href="/tbc/{{ part }}/">{{ tzo.getPartWithDots(part) }}_{{ strings["part_"~part].label }}</a>
|
||||
<a href="/tbc/{{ part.part }}/">{{ part.getNumberWithDots() }}_{{ part.getLabel() }}</a>
|
||||
</h3>
|
||||
|
||||
{% for chapter_description in strings["part_"~part].toc %}
|
||||
{% for chapter_description in part.getTableOfContents() %}
|
||||
<p>
|
||||
<a href="/tbc/{{ part }}/#chapter{{ chapter_number }}">({% if chapter_number <= 9 %} {% endif %}{{ chapter_number }}{% if chapter_number <= 9 %} {% endif %})</a> {{ chapter_description }}
|
||||
<a href="/tbc/{{ part.part }}/#chapter{{ chapter_number }}">({% if chapter_number <= 9 %} {% endif %}{{ chapter_number }}{% if chapter_number <= 9 %} {% endif %})</a> {{ chapter_description }}
|
||||
</p>
|
||||
{% set chapter_number = chapter_number + 1 %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
|
||||
<h3><a href="{{ appendix.getUrl() }}">{{ appendix.getLabel() }}</a></h3>
|
||||
<p>{{ appendix.getTableOfContents()[0] }}</p>
|
||||
</div>
|
@ -8,4 +8,4 @@ books: Works
|
||||
tzo: "There Beyond Clouds"
|
||||
tzo_full_title: "There Beyond Clouds: A Brief Guide"
|
||||
tzo_brief_guide: "A Brief Guide"
|
||||
tzo_meta_part_description: "There Beyond Clouds, section %s"
|
||||
tzo_meta_part_description: "There Beyond Clouds, section %s"
|
Loading…
x
Reference in New Issue
Block a user