diff options
| author | Elvis Claros Castro <elvis@claros.ar> | 2026-09-26 20:21:47 -0300 |
|---|---|---|
| committer | Elvis Claros Castro <elvis@claros.ar> | 2026-09-26 20:21:47 -0300 |
| commit | 59355909f2de9236af8168a26c70bcf6caa3b285 (patch) | |
| tree | 686186e2086f81aa22ad25e78eb29fca3cbadc9a /scenes/v3_cumple.py | |
| download | 100cia-videos-59355909f2de9236af8168a26c70bcf6caa3b285.tar.gz 100cia-videos-59355909f2de9236af8168a26c70bcf6caa3b285.zip | |
Import video pipeline as it was
Diffstat (limited to 'scenes/v3_cumple.py')
| -rw-r--r-- | scenes/v3_cumple.py | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/scenes/v3_cumple.py b/scenes/v3_cumple.py new file mode 100644 index 0000000..ba9dd79 --- /dev/null +++ b/scenes/v3_cumple.py @@ -0,0 +1,143 @@ +# -*- coding: utf-8 -*- +import sys, os, itertools +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +from manim import * +from tiktok import * + +N = 23 +CX, CY, R = 0.0, 2.95, 2.78 + + +def prob(n): + p = 1.0 + for k in range(n): + p *= (365 - k) / 365 + return 1 - p + + +class Cumple(TikTok): + NAME = "cumple" + + def construct(self): + self.prepare() + chip = self.chip("Paradoja del cumpleaños", CELESTE) + + pts = [np.array([CX + R * np.cos(a), CY + R * np.sin(a), 0]) + for a in np.linspace(PI / 2, PI / 2 + TAU, N, endpoint=False)] + people = VGroup(*[Dot(p, radius=0.17, color="#8FB8FF") for p in pts]) + + with self.beat(0) as b: + q = self.fit(Text("¿cuánta gente hace falta?", font=FONT, font_size=50, + weight=BOLD, color=WHITE), 8.0).move_to(UP * 3.3) + q2 = self.fit(Text("para que dos cumplan el mismo día", font=FONT, + font_size=36, color=GRIS), 8.0).next_to(q, DOWN, buff=0.35) + b.play(FadeIn(chip, shift=DOWN * 0.3), run_time=0.45) + b.play(Write(q), run_time=0.9) + b.play(FadeIn(q2, shift=UP * 0.15), run_time=0.6) + + with self.beat(1) as b: + guess = Text("¿180?", font=FONT, font_size=62, weight=BOLD, color=GRIS).move_to(UP * 0.4) + cross = Cross(guess, stroke_color=ROSA, stroke_width=11, scale_factor=0.75) + ans = Text("23", font=FONT, font_size=170, weight=BOLD, color=AMBAR).move_to(DOWN * 2.2) + b.play(FadeOut(VGroup(q, q2)), run_time=0.3) + b.play(FadeIn(guess), run_time=0.4) + b.play(Create(cross), run_time=0.45) + b.play(FadeIn(ans, scale=0.55), run_time=0.7) + b.play(Flash(ans, color=AMBAR, line_length=0.8, num_lines=20, flash_radius=2.0), + run_time=0.6) + + with self.beat(2) as b: + b.play(FadeOut(VGroup(guess, cross)), + ans.animate.scale(0.40).move_to(DOWN * 2.8), run_time=0.6) + lbl = Text("personas → 50%", font=FONT, font_size=38, weight=BOLD, color=VERDE) + lbl.next_to(ans, RIGHT, buff=0.35) + grp = VGroup(ans, lbl) + grp.move_to(DOWN * 2.8) + b.play(LaggedStart(*[GrowFromCenter(d) for d in people], lag_ratio=0.06), + run_time=1.1) + b.play(FadeIn(lbl, shift=LEFT * 0.2), run_time=0.5) + + # --- el error: uno contra todos --- + with self.beat(3) as b: + hero = people[0] + spokes = VGroup(*[Line(pts[0], pts[k], stroke_width=3.5, color=AMBAR) + for k in range(1, N)]) + cnt = Text("22 comparaciones", font=FONT, font_size=40, weight=BOLD, + color=AMBAR).move_to(DOWN * 1.3) + b.play(hero.animate.set_color(AMBAR).scale(1.6), run_time=0.4) + b.play(LaggedStart(*[Create(s) for s in spokes], lag_ratio=0.05), run_time=1.3) + b.play(FadeIn(cnt, shift=UP * 0.15), run_time=0.5) + + # --- todos contra todos --- + pairs = list(itertools.combinations(range(N), 2)) + with self.beat(4) as b: + chords = VGroup(*[Line(pts[i], pts[j], stroke_width=1.7, + color="#4CC9F0", stroke_opacity=0.5) + for i, j in pairs]) + b.play(FadeOut(spokes), FadeOut(cnt), + hero.animate.set_color("#8FB8FF").scale(1 / 1.6), run_time=0.5) + b.play(LaggedStart(*[Create(c) for c in chords], lag_ratio=0.004), + run_time=max(1.4, b.floor - 0.9)) + + with self.beat(5) as b: + big = Text("253", font=FONT, font_size=112, weight=BOLD, color=CELESTE) + cap = Text("parejas posibles", font=FONT, font_size=38, weight=BOLD, color=WHITE) + box = VGroup(big, cap).arrange(DOWN, buff=0.18).move_to(DOWN * 1.1) + b.play(FadeIn(big, scale=0.6), run_time=0.6) + b.play(FadeIn(cap, shift=UP * 0.15), run_time=0.5) + + with self.beat(6) as b: + b.play(Circumscribe(box, color=CELESTE, buff=0.35, stroke_width=6), run_time=1.0) + b.wait(0.3) + + # --- la curva --- + axes = Axes(x_range=[0, 70, 10], y_range=[0, 100, 25], + x_length=7.4, y_length=5.0, + axis_config=dict(color="#4A5878", stroke_width=4, + include_tip=False, font_size=26), + y_axis_config=dict(include_numbers=True, + numbers_to_include=[0, 50, 100])) + axes.move_to(UP * 2.15) + xlab = Text("personas", font=FONT, font_size=30, color=GRIS).next_to(axes, DOWN, buff=0.3) + curve = axes.plot(lambda n: prob(int(n)) * 100, x_range=[1, 70, 1], + color=AMBAR, stroke_width=8) + + with self.beat(7) as b: + b.play(FadeOut(VGroup(people, chords, box, grp)), run_time=0.5) + b.play(Create(axes), FadeIn(xlab), run_time=0.8) + b.play(Create(curve), run_time=max(0.9, b.floor - 1.5)) + + marks = VGroup() + + def mark(n, txt, col): + d = Dot(axes.c2p(n, prob(n) * 100), radius=0.13, color=col) + t = Text(txt, font=FONT, font_size=34, weight=BOLD, color=col) + t.next_to(d, DOWN, buff=0.28) + return VGroup(d, t) + + with self.beat(7 if False else 8) as b: + m50 = mark(50, "97%", VERDE) + m50[1].next_to(m50[0], DOWN, buff=0.35).shift(LEFT * 0.35) + m30 = mark(30, "70%", CELESTE) + m30[1].next_to(m30[0], RIGHT, buff=0.3).shift(DOWN * 0.35) + b.play(FadeIn(m30[0], scale=0.5), Write(m30[1]), run_time=0.7) + b.wait(0.2) + marks.add(m30) + b.play(FadeIn(m50[0], scale=0.5), Write(m50[1]), run_time=0.7) + marks.add(m50) + + with self.beat(9) as b: + m70 = mark(70, "99,9%", AMBAR) + m70[1].next_to(m70[0], UP, buff=0.3).shift(LEFT * 0.55) + b.play(FadeIn(m70[0], scale=0.5), Write(m70[1]), run_time=0.8) + b.play(Flash(m70[0], color=AMBAR, line_length=0.5, num_lines=16, + flash_radius=1.0), run_time=0.7) + marks.add(m70) + + with self.beat(10) as b: + cta = self.fit(Text("probalo en tu grupo", font=FONT, font_size=64, + weight=BOLD, color=AMBAR), 7.9).move_to(DOWN * 2.1) + b.play(Write(cta), run_time=0.9) + b.play(Circumscribe(cta, color=AMBAR, buff=0.3, stroke_width=7), run_time=1.0) + + self.finish() |