aboutsummaryrefslogtreecommitdiffstats
path: root/scenes/v6_benford.py
blob: 58cf420c213cefbb4fbb89e2ab915534afc05226 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# -*- coding: utf-8 -*-
import sys, os, math
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from manim import *
from tiktok import *

BENF = [math.log10(1 + 1 / d) for d in range(1, 10)]     # Benford's law
PLANO = [1 / 9] * 9                                       # what one would expect
BASE_Y, MAXH, BW = -0.9, 4.6, 0.72
XS = [-3.52 + i * 0.88 for i in range(9)]


class Benford(TikTok):
    NAME = "benford"

    def bar(self, i, frac, color):
        h = max(frac / 0.31 * MAXH, 0.02)
        r = Rectangle(width=BW, height=h, stroke_width=0, fill_color=color, fill_opacity=1)
        r.move_to([XS[i], BASE_Y, 0], DOWN)
        return r

    def construct(self):
        self.prepare()
        chip = self.chip("Estadística forense", C_GREEN)

        # ---- list of numbers -----
        raw = ["1.243", "87", "2.910", "146", "3.502", "1.078", "254", "19.640"]
        item_list = VGroup(*[Text(n, font=FONT, font_size=46, weight=BOLD, color=WHITE)
                         for n in raw]).arrange_in_grid(4, 2, buff=(1.1, 0.42))
        item_list.move_to(UP * 2.4)

        with self.beat(0) as b:
            b.play(FadeIn(chip, shift=DOWN * 0.3), run_time=0.45)
            b.play(LaggedStart(*[FadeIn(t, shift=UP * 0.15) for t in item_list],
                               lag_ratio=0.12), run_time=1.3)

        with self.beat(1) as b:
            firsts = VGroup(*[t[0].copy().set_color(AMBER) for t in item_list])
            b.play(LaggedStart(*[t[0].animate.set_color(AMBER) for t in item_list],
                               lag_ratio=0.1), run_time=1.0)
            b.play(*[Indicate(t[0], color=AMBER, scale_factor=1.5) for t in item_list],
                   run_time=0.8)

        # ---- what one would expect ---
        labels = VGroup(*[Text(str(d), font=FONT, font_size=38, weight=BOLD, color=C_GRAY)
                          .move_to([XS[d - 1], BASE_Y - 0.42, 0]) for d in range(1, 10)])
        floor = Line([-4.1, BASE_Y, 0], [4.1, BASE_Y, 0], stroke_width=5, color="#3A4766")
        bars = VGroup(*[self.bar(i, PLANO[i], "#44506E") for i in range(9)])

        with self.beat(2) as b:
            b.play(FadeOut(item_list), run_time=0.4)
            b.play(Create(floor), FadeIn(labels), run_time=0.5)
            b.play(LaggedStart(*[GrowFromEdge(x, DOWN) for x in bars],
                               lag_ratio=0.07), run_time=1.0)
            exp = Text("11% cada uno", font=FONT, font_size=40, weight=BOLD, color=C_GRAY)
            exp.move_to(UP * 4.6)
            b.play(FadeIn(exp), run_time=0.45)

        # ---- reality --------
        with self.beat(3) as b:
            nb = self.bar(0, BENF[0], AMBER)
            b.play(FadeOut(exp), run_time=0.25)
            b.play(Transform(bars[0], nb), labels[0].animate.set_color(AMBER), run_time=1.0)
            pct = Text("30%", font=FONT, font_size=42, weight=BOLD, color=AMBER)
            pct.next_to(nb, UP, buff=0.18)
            b.play(FadeIn(pct, shift=UP * 0.15), run_time=0.5)

        with self.beat(4) as b:
            news = [self.bar(i, BENF[i], C_SKY) for i in range(1, 9)]
            b.play(LaggedStart(*[Transform(bars[i + 1], news[i]) for i in range(8)],
                               lag_ratio=0.1), run_time=1.4)
            p2 = Text("17%", font=FONT, font_size=34, weight=BOLD, color=C_SKY)
            p2.next_to(news[0], UP, buff=0.15)
            p9 = Text("4%", font=FONT, font_size=34, weight=BOLD, color=C_SKY)
            p9.next_to(news[7], UP, buff=0.15)
            b.play(FadeIn(p2), FadeIn(p9), run_time=0.5)

        with self.beat(5) as b:
            name = self.fit(Text("LEY DE BENFORD", font=FONT, font_size=62,
                                 weight=BOLD, color=WHITE), 8.0).move_to(UP * 4.7)
            b.play(Write(name), run_time=1.0)

        with self.beat(6) as b:
            words = VGroup(*[Text(w, font=FONT, font_size=34, color=C_GRAY)
                             for w in ("poblaciones", "precios", "likes", "ríos")])
            words.arrange(RIGHT, buff=0.45).move_to(DOWN * 1.9)
            self.fit(words, 8.2)
            b.play(LaggedStart(*[FadeIn(w, shift=UP * 0.15) for w in words],
                               lag_ratio=0.25), run_time=1.1)

        # ---- the made-up numbers -------
        with self.beat(7) as b:
            b.play(FadeOut(words), run_time=0.3)
            fake = VGroup(*[Rectangle(width=BW, height=PLANO[i] / 0.31 * MAXH,
                                      stroke_color=C_PINK, stroke_width=5,
                                      fill_opacity=0).move_to([XS[i], BASE_Y, 0], DOWN)
                            for i in range(9)])
            lbl = Text("inventados", font=FONT, font_size=42, weight=BOLD, color=C_PINK)
            lbl.move_to(DOWN * 2.0)
            b.play(LaggedStart(*[Create(f) for f in fake], lag_ratio=0.07), run_time=1.1)
            b.play(FadeIn(lbl, shift=UP * 0.15), run_time=0.5)

        with self.beat(8) as b:
            b.play(*[Indicate(fake[i], color=C_PINK, scale_factor=1.06) for i in (0, 1)],
                   run_time=0.8)
            gap = DoubleArrow(fake[0].get_top() + UP * 0.08, bars[0].get_top() + DOWN * 0.08,
                              buff=0, color=C_PINK, stroke_width=7,
                              tip_length=0.22).shift(RIGHT * 0.0)
            b.play(GrowArrow(gap), run_time=0.7)
            b.play(Flash(gap, color=C_PINK, line_length=0.4, num_lines=14,
                         flash_radius=1.0), run_time=0.6)

        with self.beat(9) as b:
            b.play(FadeOut(VGroup(fake, gap, lbl)), run_time=0.4)
            txt = VGroup(
                self.fit(Text("así agarraron", font=FONT, font_size=46,
                              weight=BOLD, color=WHITE), 8.0),
                self.fit(Text("fraudes contables reales", font=FONT, font_size=46,
                              weight=BOLD, color=C_PINK), 8.0),
            ).arrange(DOWN, buff=0.3).move_to(DOWN * 2.1)
            b.play(FadeIn(txt[0], shift=UP * 0.15), run_time=0.5)
            b.play(FadeIn(txt[1], shift=UP * 0.15), run_time=0.6)

        with self.beat(10) as b:
            count_txt = self.fit(Text("probá con tu tarjeta", font=FONT, font_size=58,
                                weight=BOLD, color=AMBER), 7.9).move_to(DOWN * 3.15)
            b.play(FadeOut(txt), run_time=0.3)
            b.play(Write(count_txt), run_time=0.9)
            b.play(Circumscribe(count_txt, color=AMBER, buff=0.28, stroke_width=7), run_time=1.0)

        self.finish()