今日のラッキーナンバーウィジェット
設定難易度

今日のラッキー数字をホーム画面に表示できる、Scriptable用ウィジェットです。

最初は単純に「今日のラッキーナンバー」を表示するだけのものを考えていましたが、せっかく数字を出すならナンバーズやロトにも使えたら面白いんじゃないかと思い、いろいろなモードを追加しました。

シンプルに1〜9から今日の数字を1つ表示する「ラッキー」のほか、ナンバーズ3・ナンバーズ4・ミニロト・ロト6・ロト7にも対応しています。

表示される数字は日付をもとに生成しているので、同じ日は何度更新しても基本的に同じ数字。
日付が変わると新しい数字に切り替わります。

もちろん当選を予測するものではありませんが、「今日はどの数字にしよう?」と迷ったときに、ちょっとした運試しとして使ってみてください。

ウィジェットの表示内容

日付とモードを使って数字を作るため、同じ日の同じモードでは結果が変わりません。

サイズごとの表示

  • 表示する数字のモードは、小・中・大で共通です。サイズを変えると文字の大きさや配置が変わります。
  • ラッキー、ナンバーズ3・4、ミニロト、ロト6・7から選んだモードに合わせて数字を作ります。

設定手順

上から順に進めてください。コードの保存と設定のコピーに必要な操作欄は、それぞれの手順の中にあります。

  1. Scriptableを用意する

    App StoreでScriptableを開き、iPhoneにインストールします。すでに入っている場合は次へ進んでください。

  2. コードをコピーして保存する

    下のコード欄の「コピー」を押します。Scriptableへ移動し、「+」から新しいスクリプトを作ってコード全文を貼り付け、今日のラッキーナンバーなどの名前で保存してください。

    保存したらこのページに戻り、次の手順へ進みます。

    // Version: 1.0.0
    // =====================================================
    // 今日のラッキー数字 - Scriptable Widget
    // =====================================================
    //
    // 【使い方】
    // ホーム画面のウィジェットを長押し
    // →「ウィジェットを編集」
    // → Parameter に以下のいずれかを入力
    //
    // ラッキー
    // ナンバーズ3
    // ナンバーズ4
    // ミニロト
    // ロト6
    // ロト7
    //
    // 同じ日は何度更新しても同じ数字になります。
    // 日付が変わると、新しい数字に自動更新されます。
    //
    // ※表示される数字は娯楽目的のランダム生成です。
    //   当選を予測・保証するものではありません。
    // =====================================================
    
    
    // =====================================================
    // 基本設定
    // =====================================================
    
    const rawParameter =
      typeof args !== "undefined" && args.widgetParameter
        ? args.widgetParameter.trim()
        : "";
    
    const mode = rawParameter || "ラッキー";
    
    
    // =====================================================
    // モード設定
    // =====================================================
    
    const modes = {
      "ラッキー": {
        title: "今日のラッキー数字",
        type: "lucky",
        min: 1,
        max: 9,
        count: 1,
        duplicate: false
      },
    
      "ナンバーズ3": {
        title: "NUMBERS 3",
        subtitle: "今日のラッキーナンバー",
        type: "numbers",
        min: 0,
        max: 9,
        count: 3,
        duplicate: true
      },
    
      "ナンバーズ4": {
        title: "NUMBERS 4",
        subtitle: "今日のラッキーナンバー",
        type: "numbers",
        min: 0,
        max: 9,
        count: 4,
        duplicate: true
      },
    
      "ミニロト": {
        title: "MINI LOTO",
        subtitle: "今日のラッキーナンバー",
        type: "loto",
        min: 1,
        max: 31,
        count: 5,
        duplicate: false
      },
    
      "ロト6": {
        title: "LOTO 6",
        subtitle: "今日のラッキーナンバー",
        type: "loto",
        min: 1,
        max: 43,
        count: 6,
        duplicate: false
      },
    
      "ロト7": {
        title: "LOTO 7",
        subtitle: "今日のラッキーナンバー",
        type: "loto",
        min: 1,
        max: 37,
        count: 7,
        duplicate: false
      }
    };
    
    
    // =====================================================
    // モード確認
    // =====================================================
    
    const setting = modes[mode] || modes["ラッキー"];
    
    
    // =====================================================
    // 今日の日付
    // =====================================================
    
    const now = new Date();
    
    const year = now.getFullYear();
    const month = now.getMonth() + 1;
    const day = now.getDate();
    
    const dateText =
      `${year}.${String(month).padStart(2, "0")}.${String(day).padStart(2, "0")}`;
    
    const seedText =
      `${year}-${month}-${day}-${mode}`;
    
      
    // =====================================================
    // シード値生成
    // =====================================================
    
    function stringToSeed(str) {
      let hash = 2166136261;
    
      for (let i = 0; i < str.length; i++) {
        hash ^= str.charCodeAt(i);
        hash = Math.imul(hash, 16777619);
      }
    
      return hash >>> 0;
    }
    
    
    // =====================================================
    // シード付き乱数
    // =====================================================
    
    function seededRandom(seed) {
    
      let value = seed >>> 0;
    
      return function () {
    
        value += 0x6D2B79F5;
    
        let t = value;
    
        t = Math.imul(t ^ (t >>> 15), t | 1);
        t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
    
        return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
      };
    }
    
    
    // =====================================================
    // 数字生成
    // =====================================================
    
    function generateNumbers(setting) {
    
      const seed = stringToSeed(seedText);
      const random = seededRandom(seed);
    
      const result = [];
    
      while (result.length < setting.count) {
    
        const number =
          Math.floor(
            random() * (setting.max - setting.min + 1)
          ) + setting.min;
    
        if (
          setting.duplicate ||
          !result.includes(number)
        ) {
          result.push(number);
        }
      }
    
      // ロト系のみ昇順
      if (setting.type === "loto") {
        result.sort((a, b) => a - b);
      }
    
      return result;
    }
    
    
    const numbers = generateNumbers(setting);
    
    
    // =====================================================
    // ウィジェット
    // =====================================================
    
    const widget = new ListWidget();
    
    
    // =====================================================
    // 背景
    // =====================================================
    
    const gradient = new LinearGradient();
    
    gradient.colors = [
      new Color("#151829"),
      new Color("#252A46")
    ];
    
    gradient.locations = [0, 1];
    
    widget.backgroundGradient = gradient;
    
    
    // =====================================================
    // サイズ判定
    // =====================================================
    
    const family =
      config.widgetFamily || "medium";
    
    
    // =====================================================
    // 共通カラー
    // =====================================================
    
    const mainColor = Color.white();
    const subColor = new Color("#A9AEC9");
    const accentColor = new Color("#FFD86B");
    
    
    // =====================================================
    // SMALL
    // =====================================================
    
    if (family === "small") {
    
      widget.setPadding(15, 15, 13, 15);
    
      if (setting.type === "lucky") {
    
        const title = widget.addText("今日の");
        title.font = Font.mediumSystemFont(12);
        title.textColor = subColor;
    
        const title2 = widget.addText("ラッキー数字");
        title2.font = Font.boldSystemFont(17);
        title2.textColor = mainColor;
    
        widget.addSpacer();
    
        const number = widget.addText(
          String(numbers[0])
        );
    
        number.font = Font.boldSystemFont(58);
        number.textColor = accentColor;
        number.centerAlignText();
    
        widget.addSpacer();
    
        const luck = widget.addText("GOOD LUCK!");
        luck.font = Font.boldSystemFont(10);
        luck.textColor = subColor;
        luck.centerAlignText();
    
      } else {
    
        const title = widget.addText(setting.title);
        title.font = Font.boldSystemFont(16);
        title.textColor = mainColor;
    
        const subtitle =
          widget.addText("LUCKY NUMBER");
    
        subtitle.font = Font.mediumSystemFont(9);
        subtitle.textColor = subColor;
    
        widget.addSpacer();
    
        if (setting.type === "numbers") {
    
          const value = numbers.join("");
    
          const number = widget.addText(value);
          number.font = Font.boldSystemFont(
            setting.count === 3 ? 42 : 36
          );
    
          number.textColor = accentColor;
          number.centerAlignText();
    
        } else {
    
          const rows =
            setting.count <= 5
              ? [numbers]
              : [
                  numbers.slice(
                    0,
                    Math.ceil(numbers.length / 2)
                  ),
                  numbers.slice(
                    Math.ceil(numbers.length / 2)
                  )
                ];
    
          for (const row of rows) {
    
            const text =
              row
                .map(n =>
                  String(n).padStart(2, "0")
                )
                .join(" ");
    
            const number = widget.addText(text);
    
            number.font =
              Font.boldSystemFont(
                setting.count === 7 ? 17 : 19
              );
    
            number.textColor = accentColor;
            number.centerAlignText();
    
            widget.addSpacer(4);
          }
        }
    
        widget.addSpacer();
    
        const date = widget.addText(dateText);
        date.font = Font.mediumSystemFont(9);
        date.textColor = subColor;
        date.centerAlignText();
      }
    }
    
    
    // =====================================================
    // MEDIUM
    // =====================================================
    
    else if (family === "medium") {
    
      widget.setPadding(18, 20, 15, 20);
    
      const title = widget.addText(setting.title);
      title.font = Font.boldSystemFont(18);
      title.textColor = mainColor;
    
      if (setting.type !== "lucky") {
    
        const subtitle =
          widget.addText(setting.subtitle);
    
        subtitle.font =
          Font.mediumSystemFont(10);
    
        subtitle.textColor = subColor;
      }
    
      widget.addSpacer();
    
      if (setting.type === "lucky") {
    
        const number =
          widget.addText(String(numbers[0]));
    
        number.font = Font.boldSystemFont(62);
        number.textColor = accentColor;
        number.centerAlignText();
    
        widget.addSpacer(2);
    
        const luck =
          widget.addText("GOOD LUCK!");
    
        luck.font = Font.boldSystemFont(10);
        luck.textColor = subColor;
        luck.centerAlignText();
    
      }
    
      else if (setting.type === "numbers") {
    
        const stack = widget.addStack();
        stack.layoutHorizontally();
        stack.centerAlignContent();
    
        stack.addSpacer();
    
        numbers.forEach((n, index) => {
    
          const number = stack.addText(String(n));
          number.font = Font.boldSystemFont(42);
          number.textColor = accentColor;
    
          if (index < numbers.length - 1) {
            stack.addSpacer(16);
          }
        });
    
        stack.addSpacer();
      }
    
      else {
    
        const stack = widget.addStack();
        stack.layoutHorizontally();
        stack.centerAlignContent();
    
        stack.addSpacer();
    
        numbers.forEach((n, index) => {
    
          const number =
            stack.addText(
              String(n).padStart(2, "0")
            );
    
          number.font =
            Font.boldSystemFont(
              setting.count === 7 ? 24 : 27
            );
    
          number.textColor = accentColor;
    
          if (index < numbers.length - 1) {
            stack.addSpacer(
              setting.count === 7 ? 8 : 12
            );
          }
        });
    
        stack.addSpacer();
      }
    
      widget.addSpacer();
    
      const date = widget.addText(dateText);
      date.font = Font.mediumSystemFont(9);
      date.textColor = subColor;
      date.rightAlignText();
    }
    
    
    // =====================================================
    // LARGE
    // =====================================================
    
    else {
    
      widget.setPadding(24, 24, 20, 24);
    
      const title = widget.addText(setting.title);
      title.font = Font.boldSystemFont(24);
      title.textColor = mainColor;
    
      if (setting.type !== "lucky") {
    
        const subtitle =
          widget.addText(setting.subtitle);
    
        subtitle.font = Font.mediumSystemFont(12);
        subtitle.textColor = subColor;
      }
    
      widget.addSpacer(30);
    
      if (setting.type === "lucky") {
    
        const number =
          widget.addText(String(numbers[0]));
    
        number.font = Font.boldSystemFont(100);
        number.textColor = accentColor;
        number.centerAlignText();
    
        widget.addSpacer(8);
    
        const luck =
          widget.addText("GOOD LUCK!");
    
        luck.font = Font.boldSystemFont(14);
        luck.textColor = subColor;
        luck.centerAlignText();
    
      }
    
      else if (setting.type === "numbers") {
    
        const stack = widget.addStack();
        stack.layoutHorizontally();
        stack.centerAlignContent();
    
        stack.addSpacer();
    
        numbers.forEach((n, index) => {
    
          const number = stack.addText(String(n));
          number.font = Font.boldSystemFont(62);
          number.textColor = accentColor;
    
          if (index < numbers.length - 1) {
            stack.addSpacer(22);
          }
        });
    
        stack.addSpacer();
      }
    
      else {
    
        const rows =
          setting.count <= 5
            ? [numbers]
            : [
                numbers.slice(
                  0,
                  Math.ceil(numbers.length / 2)
                ),
                numbers.slice(
                  Math.ceil(numbers.length / 2)
                )
              ];
    
        for (const row of rows) {
    
          const stack = widget.addStack();
          stack.layoutHorizontally();
          stack.centerAlignContent();
    
          stack.addSpacer();
    
          row.forEach((n, index) => {
    
            const number =
              stack.addText(
                String(n).padStart(2, "0")
              );
    
            number.font = Font.boldSystemFont(38);
            number.textColor = accentColor;
    
            if (index < row.length - 1) {
              stack.addSpacer(22);
            }
          });
    
          stack.addSpacer();
    
          widget.addSpacer(14);
        }
      }
    
      widget.addSpacer();
    
      const date = widget.addText(dateText);
      date.font = Font.mediumSystemFont(11);
      date.textColor = subColor;
      date.rightAlignText();
    }
    
    
    // =====================================================
    // 更新タイミング
    // 翌日の0:01以降に更新
    // =====================================================
    
    const tomorrow = new Date();
    
    tomorrow.setDate(tomorrow.getDate() + 1);
    tomorrow.setHours(0, 1, 0, 0);
    
    widget.refreshAfterDate = tomorrow;
    
    
    // =====================================================
    // 表示
    // =====================================================
    
    if (config.runsInWidget) {
    
      Script.setWidget(widget);
    
    } else {
    
      if (family === "small") {
        await widget.presentSmall();
      }
    
      else if (family === "large") {
        await widget.presentLarge();
      }
    
      else {
        await widget.presentMedium();
      }
    }
    
    Script.complete();
  3. Parameterに設定を入力する

    ウィジェットを長押しして「ウィジェットを編集」を開き、「Parameter」に使いたいモード名を1つ入力します。

    • ラッキー
    • ナンバーズ3/ナンバーズ4
    • ミニロト/ロト6/ロト7

    例:ロト6を使う場合は ロト6 と入力します。空欄の場合はラッキーナンバーになります。

  4. ホーム画面に追加して設定する

    iPhoneのホーム画面を長押しし、ウィジェット追加画面からScriptableを選びます。この記事の対応サイズの説明に合わせてサイズを選んで追加してください。

    追加したウィジェットを長押しして「ウィジェットを編集」を開き、「Script」に保存したスクリプトを選びます。

    「Parameter」に上で案内した値を直接入力します。 設定を変えるときは、この欄を書き換えてください。

    編集画面を閉じて表示を確認します。ホーム画面への反映には少し時間がかかる場合があります。

毎日数字が変わります

表示される数字は日付をもとに生成しています。
そのため、ウィジェットを何度更新しても、その日の数字は基本的に変わりません。
日付が変わると、新しい「今日のラッキー数字」に自動で切り替わります。
「更新するたびに都合のいい数字が出るまでやり直す」という誘惑もありません。
今日の数字は今日だけの数字として楽しんでください。

複数のモードを使いたい場合

同じスクリプトを使って、複数のScriptableウィジェットをホーム画面に配置できます。

例えば、

1つ目 → ラッキー
2つ目 → ナンバーズ4
3つ目 → ロト6

というように、それぞれのウィジェットのParameterを変更すればOKです。

モードごとにスクリプトを複製する必要はありません。

動作確認・使用結果

確認した端末 iPhone 17 ProMAX
iOS iOS27
Scriptable 1.7.19
確認したサイズ 小・中・大
バージョン 1.0.0
動作確認日 2026-09-18

表示・使用時のポイント

日付とモードを使って数字を作るため、同じ日の同じモードでは結果が変わりません。ナンバーズでは同じ桁が出る場合があります。

更新履歴

1.0.0

  • 初回リリース

よくあるエラーと対処

確認すること
表示されない場合は、ウィジェット編集画面の「Script」に保存したスクリプトが選ばれているかも確認してください。コードを貼り直すときは全文を置き換えます。
数字が変わらない
日付が変わるまで同じ数字になる仕様です。
希望するモードにならない
設定欄でモードを選び直し、生成した値をParameterへ貼り直してください。

注意事項・制限

  • このウィジェットで表示される数字は、日付をもとに生成した娯楽目的のラッキーナンバーです。
    宝くじの当選番号を予測するものではなく、当選を保証するものでもありません。
    ナンバーズ・ロトモードについても、数字選びを楽しむための参考としてご利用ください。
  • 数字を楽しむためのツールです。抽せん結果の予測や当せんの保証はしません。
  • モードによって数字の範囲と個数、重複の扱いが異なります。
  • ホーム画面の更新タイミングはiOSが管理するため、操作やデータの変更がすぐに反映されない場合があります。

データ提供・参考資料

このウィジェットにはデータ提供や参考資料は特にありません。

SHARE

この記事をシェア