aboutsummaryrefslogtreecommitdiffstats
path: root/scenes/v1_montyhall.py
diff options
context:
space:
mode:
authorElvis Claros Castro <elvis@claros.ar>2026-09-26 20:21:47 -0300
committerElvis Claros Castro <elvis@claros.ar>2026-09-26 20:21:47 -0300
commit59355909f2de9236af8168a26c70bcf6caa3b285 (patch)
tree686186e2086f81aa22ad25e78eb29fca3cbadc9a /scenes/v1_montyhall.py
download100cia-videos-59355909f2de9236af8168a26c70bcf6caa3b285.tar.gz
100cia-videos-59355909f2de9236af8168a26c70bcf6caa3b285.zip
Import video pipeline as it was
Diffstat (limited to 'scenes/v1_montyhall.py')
-rw-r--r--scenes/v1_montyhall.py166
1 files changed, 166 insertions, 0 deletions
diff --git a/scenes/v1_montyhall.py b/scenes/v1_montyhall.py
new file mode 100644
index 0000000..bdaf6c5
--- /dev/null
+++ b/scenes/v1_montyhall.py
@@ -0,0 +1,166 @@
+# -*- coding: utf-8 -*-
+import sys, os
+sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
+from manim import *
+from tiktok import *
+
+DOOR_Y, DW, DH = 4.0, 2.5, 3.7
+XS = [-2.85, 0.0, 2.85]
+
+
+class MontyHall(TikTok):
+ NAME = "montyhall"
+
+ def door(self, n, x):
+ face = RoundedRectangle(corner_radius=0.18, width=DW, height=DH,
+ stroke_color="#2E3A55", stroke_width=6,
+ fill_color="#16203A", fill_opacity=1)
+ num = Text(str(n), font=FONT, font_size=104, weight=BOLD, color="#5B6B8C")
+ knob = Dot(radius=0.1, color="#5B6B8C").move_to(face.get_right() + LEFT * 0.36)
+ d = VGroup(face, num, knob).move_to([x, DOOR_Y, 0])
+ d.face, d.num, d.knob = face, num, knob
+ return d
+
+ def badge(self, text, color, fs=30):
+ t = Text(text, font=FONT, font_size=fs, weight=BOLD, color="#0B0F1A")
+ box = RoundedRectangle(corner_radius=0.2, width=t.width + 0.5, height=t.height + 0.42,
+ stroke_width=0, fill_color=color, fill_opacity=1)
+ return VGroup(box, t)
+
+ def car_icon(self, color=VERDE):
+ body = RoundedRectangle(corner_radius=0.14, width=1.6, height=0.6,
+ stroke_width=0, fill_color=color, fill_opacity=1)
+ roof = RoundedRectangle(corner_radius=0.12, width=0.92, height=0.48,
+ stroke_width=0, fill_color=color, fill_opacity=1)
+ roof.next_to(body, UP, buff=-0.08)
+ w1 = Dot(radius=0.19, color="#0B0F1A").move_to(body.get_bottom() + LEFT * 0.48)
+ w2 = Dot(radius=0.19, color="#0B0F1A").move_to(body.get_bottom() + RIGHT * 0.48)
+ return VGroup(roof, body, w1, w2)
+
+ def goat_icon(self, color="#94A3B8"):
+ head = Ellipse(width=1.05, height=0.72, stroke_width=0, fill_color=color, fill_opacity=1)
+ snout = Ellipse(width=0.5, height=0.36, stroke_width=0, fill_color=color, fill_opacity=1)
+ snout.move_to(head.get_bottom() + DOWN * 0.1)
+ h1 = ArcBetweenPoints(head.get_top() + LEFT * 0.26, head.get_top() + LEFT * 0.62 + UP * 0.42,
+ angle=-1.1, stroke_width=8, color=color)
+ h2 = ArcBetweenPoints(head.get_top() + RIGHT * 0.26, head.get_top() + RIGHT * 0.62 + UP * 0.42,
+ angle=1.1, stroke_width=8, color=color)
+ e1 = Dot(radius=0.07, color="#0B0F1A").move_to(head.get_center() + LEFT * 0.22 + UP * 0.06)
+ e2 = Dot(radius=0.07, color="#0B0F1A").move_to(head.get_center() + RIGHT * 0.22 + UP * 0.06)
+ return VGroup(h1, h2, head, snout, e1, e2)
+
+ def prize(self, kind, x):
+ if kind == "auto":
+ g = VGroup(self.car_icon(), self.badge("AUTO", VERDE))
+ else:
+ g = VGroup(self.goat_icon(), self.badge("CABRA", "#94A3B8"))
+ g.arrange(DOWN, buff=0.3)
+ return g.move_to([x, DOOR_Y, 0])
+
+ def construct(self):
+ self.prepare()
+ chip = self.chip("¿Cambiarías de puerta?")
+ doors = VGroup(*[self.door(i + 1, XS[i]) for i in range(3)])
+
+ with self.beat(0) as b:
+ b.play(FadeIn(chip, shift=DOWN * 0.3), run_time=0.5)
+ b.play(LaggedStart(*[GrowFromCenter(d) for d in doors], lag_ratio=0.25), run_time=1.2)
+ h1 = VGroup(self.car_icon().scale(0.85),
+ Text("×1", font=FONT, font_size=46, weight=BOLD, color=VERDE)
+ ).arrange(RIGHT, buff=0.35).move_to(UP * 1.3)
+ b.play(FadeIn(h1, shift=UP * 0.2), run_time=0.5)
+
+ with self.beat(1) as b:
+ h2 = VGroup(self.goat_icon().scale(0.85),
+ Text("×2", font=FONT, font_size=46, weight=BOLD, color="#94A3B8")
+ ).arrange(RIGHT, buff=0.35)
+ h2.next_to(h1, DOWN, buff=0.55)
+ b.play(FadeIn(h2, shift=UP * 0.2), run_time=0.6)
+ b.wait(0.5)
+ b.play(FadeOut(VGroup(h1, h2)), run_time=0.4)
+
+ with self.beat(2) as b:
+ pick = Text("TU ELECCIÓN", font=FONT, font_size=38, weight=BOLD, color=AMBAR)
+ arrow = Arrow(doors[0].get_bottom() + DOWN * 1.3, doors[0].get_bottom() + DOWN * 0.12,
+ buff=0, color=AMBAR, stroke_width=10)
+ pick.next_to(arrow, DOWN, buff=0.18)
+ b.play(doors[0].face.animate.set_stroke(AMBAR, 11),
+ doors[0].num.animate.set_color(AMBAR), run_time=0.5)
+ b.play(GrowArrow(arrow), FadeIn(pick), run_time=0.5)
+ picked = VGroup(pick, arrow)
+
+ with self.beat(3) as b:
+ goat = self.prize("cabra", XS[2])
+ b.play(doors[2].face.animate.set_fill("#0E1526", 1).set_stroke("#2E3A55", 4),
+ FadeOut(doors[2].num), FadeOut(doors[2].knob), run_time=0.7)
+ b.play(FadeIn(goat, scale=0.75), run_time=0.7)
+ doors[2].remove(doors[2].num, doors[2].knob)
+ b.play(VGroup(doors[2], goat).animate.set_opacity(0.35), run_time=0.5)
+
+ with self.beat(4) as b:
+ q = Text("¿1 o 2?", font=FONT, font_size=82, weight=BOLD, color=WHITE).move_to(UP * 1.0)
+ b.play(FadeOut(picked), run_time=0.3)
+ b.play(Write(q), doors[1].face.animate.set_stroke(CELESTE, 10),
+ doors[1].num.animate.set_color(CELESTE), run_time=1.0)
+
+ with self.beat(5) as b:
+ fifty = Text("50% / 50%", font=FONT, font_size=68, weight=BOLD, color=GRIS)
+ fifty.move_to(DOWN * 1.5)
+ cross = VGroup(
+ Line(fifty.get_corner(UL), fifty.get_corner(DR), stroke_width=14, color=ROSA),
+ Line(fifty.get_corner(DL), fifty.get_corner(UR), stroke_width=14, color=ROSA),
+ )
+ b.play(FadeIn(fifty), run_time=0.5)
+ b.wait(0.6)
+ b.play(Create(cross), run_time=0.6)
+ b.play(FadeOut(VGroup(fifty, cross, q)), run_time=0.5)
+
+ with self.beat(6) as b:
+ f1 = MathTex(r"\tfrac{1}{3}", color=AMBAR).scale(2.6).next_to(doors[0], DOWN, buff=0.7)
+ cap1 = Text("lo que tenías al elegir", font=FONT, font_size=34, color=GRIS)
+ cap1.next_to(f1, DOWN, buff=0.45).set_x(0)
+ b.play(Write(f1), run_time=0.8)
+ b.play(FadeIn(cap1), run_time=0.5)
+
+ with self.beat(7) as b:
+ brace = Brace(VGroup(doors[1], doors[2]), DOWN, color=CELESTE, buff=0.28)
+ f2 = MathTex(r"\tfrac{2}{3}", color=CELESTE).scale(2.6).next_to(brace, DOWN, buff=0.25)
+ b.play(FadeOut(cap1), run_time=0.25)
+ b.play(GrowFromCenter(brace), run_time=0.5)
+ b.play(Write(f2), run_time=0.7)
+
+ with self.beat(8) as b:
+ dest = f1.get_center() + RIGHT * (XS[1] - XS[0])
+ b.play(FadeOut(brace), run_time=0.3)
+ b.play(f2.animate.move_to(dest), run_time=1.2)
+ b.play(Flash(f2, color=CELESTE, line_length=0.6, num_lines=18, flash_radius=1.4),
+ doors[1].face.animate.set_fill("#123A57", 1), run_time=0.9)
+
+ with self.beat(9) as b:
+ b.play(FadeOut(VGroup(doors, f1, f2, goat)), run_time=0.5)
+ rows = []
+ for lbl, pct, col in (("QUEDARSE", 0.333, ROSA), ("CAMBIAR", 0.667, VERDE)):
+ name = Text(lbl, font=FONT, font_size=46, weight=BOLD, color=col)
+ track = RoundedRectangle(corner_radius=0.12, width=7.0, height=0.85, stroke_width=0,
+ fill_color="#1B2233", fill_opacity=1)
+ fill = RoundedRectangle(corner_radius=0.12, width=7.0 * pct, height=0.85,
+ stroke_width=0, fill_color=col, fill_opacity=1)
+ fill.move_to(track.get_left(), LEFT)
+ val = Text(f"{round(pct*100)}%", font=FONT, font_size=58, weight=BOLD, color=col)
+ rows.append(VGroup(name, VGroup(track, fill), val).arrange(DOWN, buff=0.25))
+ board = VGroup(*rows).arrange(DOWN, buff=1.0).move_to(UP * 2.2)
+ b.play(*[FadeIn(r[0]) for r in rows], *[FadeIn(r[1][0]) for r in rows], run_time=0.5)
+ for r in rows:
+ f, w = r[1][1], r[1][1].width
+ f.stretch_to_fit_width(0.002).move_to(r[1][0].get_left(), LEFT)
+ b.play(f.animate.stretch_to_fit_width(w).move_to(r[1][0].get_left(), LEFT),
+ FadeIn(r[2]), run_time=0.8)
+ b.wait(0.3)
+
+ with self.beat(10) as b:
+ cta = self.fit(Text("CAMBIÁ SIEMPRE", font=FONT, font_size=70,
+ weight=BOLD, color=AMBAR), 7.9).move_to(DOWN * 1.9)
+ b.play(Write(cta), run_time=0.9)
+ b.play(Circumscribe(cta, color=AMBAR, buff=0.35, stroke_width=8), run_time=1.1)
+
+ self.finish()