# -*- 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=C_GREEN): 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", C_GREEN)) 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=C_GREEN) ).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=AMBER) arrow = Arrow(doors[0].get_bottom() + DOWN * 1.3, doors[0].get_bottom() + DOWN * 0.12, buff=0, color=AMBER, stroke_width=10) pick.next_to(arrow, DOWN, buff=0.18) b.play(doors[0].face.animate.set_stroke(AMBER, 11), doors[0].num.animate.set_color(AMBER), 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(C_SKY, 10), doors[1].num.animate.set_color(C_SKY), run_time=1.0) with self.beat(5) as b: fifty = Text("50% / 50%", font=FONT, font_size=68, weight=BOLD, color=C_GRAY) fifty.move_to(DOWN * 1.5) cross = VGroup( Line(fifty.get_corner(UL), fifty.get_corner(DR), stroke_width=14, color=C_PINK), Line(fifty.get_corner(DL), fifty.get_corner(UR), stroke_width=14, color=C_PINK), ) 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=AMBER).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=C_GRAY) 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=C_SKY, buff=0.28) f2 = MathTex(r"\tfrac{2}{3}", color=C_SKY).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=C_SKY, 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, C_PINK), ("CAMBIAR", 0.667, C_GREEN)): 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: count_txt = self.fit(Text("CAMBIÁ SIEMPRE", font=FONT, font_size=70, weight=BOLD, color=AMBER), 7.9).move_to(DOWN * 1.9) b.play(Write(count_txt), run_time=0.9) b.play(Circumscribe(count_txt, color=AMBER, buff=0.35, stroke_width=8), run_time=1.1) self.finish()