• [Javascript] Broadcaster + Operator + Listener pattern -- 17. Building a Word Matching Game


    It's common for a user to enter values that you want to check against your pre-defined values. Let's make a demo of a word game to demonstrate one approach to solving that use case.

    Try consolidating map(hangmanLogic) even further into a stand-alone hangmanLogic operator so that there's no mapping, just the hangmanLogic operator

    import { addListener, done, forOf } from "./broadcasters";
    import { targetValue } from "./operators";
    
    const log = console.log;
    
    let inputInput = addListener("#input", "input");
    let inputValue = targetValue(inputInput);
    
    let word = forOf("honeycomb");
    
    inputValue((value) => {
      let result = "";
      word((letter) => {
        if (letter === done) {
          console.log(result);
          return
        }
        if (value.includes(letter)) {
          result += letter;
        } else {
          result += "*";
        }
      });
    });
    
    /*
    h**e***** 
    honeycomb 
    */

    We have outside 'inputValue' to provde value and inside 'word' providing innerValue.

    1. Model the behavior for tow broadcasters: "inputValue" & "word".

    The logic is "inputValue", inside, it doesn't mapping to a transform function but to another broadcaster: word.

    So create a operator called mapBroadcaster:

    let mapBroadcaster = createBroadcaster => broadcaster => listener => {
      broadcaster(value => {
        let newBroadcaster = createBroadcaster(value)
        newBroadcaster(listener)
      })
    }
    
    mapBroadcaster(value => word)(inputValue)(log)

    2. Apply logic to inner broadcaster 'word':

    logic we want to apply:

        if (value.includes(letter)) {
          result += letter;
        } else {
          result += "*";
        }

    then:

    let mapBroadcaster = (createBroadcaster) => (broadcaster) => (listener) => {
      broadcaster((value) => {
        let newBroadcaster = createBroadcaster(value);
        newBroadcaster(listener);
      });
    };
    
    mapBroadcaster((value) => {
      return map((letter) => (value.includes(letter) ? letter : "*"))(word);
    })(inputValue)(log);

    Equals to:

    mapBroadcaster((value) => {
      return mapBroadcaster((operator) => operator(word))(
        map((value) => {
          return map((letter) => (value.includes(letter) ? letter : "*"));
        })(inputValue)
      );
    })(log);

    Pattern to catch: 

    inputValue(value => logicFn)(listener)
    
    // equals to 
    
    map(value => logicFn)(inputValue)(listener)

    Refect again:

    let hangmanLogic = (value) => {
      return map((letter) => (value.includes(letter) ? letter : "*"));
    };
    
    mapBroadcaster((value) => {
      return mapBroadcaster((operator) => operator(word))(
        map(hangmanLogic)(inputValue)
      );
    })(log);

    3. Add helper function 'applyBroadcaster':

    Catching this pattern:

    mapBroadcaster((operator) => operator(word))

    so:

    let mapBroadcaster = (createBroadcaster) => (broadcaster) => (listener) => {
      broadcaster((value) => {
        let newBroadcaster = createBroadcaster(value);
        newBroadcaster(listener);
      });
    };
    
    let hangmanLogic = (value) => {
      return map((letter) => (value.includes(letter) ? letter : "*"));
    };
    
    let applyOperator = broadcaster => mapBroadcaster(operator => operator(broadcaster))
    
    applyOperator(word)(
        map(hangmanLogic)(inputValue)
      )(log);

    4. Apply "pipe":

    let mapBroadcaster = (createBroadcaster) => (broadcaster) => (listener) => {
      broadcaster((value) => {
        let newBroadcaster = createBroadcaster(value);
        newBroadcaster(listener);
      });
    };
    
    let hangmanLogic = (value) => {
      return map((letter) => (value.includes(letter) ? letter : "*"));
    };
    
    let applyOperator = (broadcaster) =>
      mapBroadcaster((operator) => operator(broadcaster));
    
    let hangman = pipe(map(hangmanLogic), applyOperator(word));
    hangman(inputValue)(log);

    5. Applying the rest of logic:

    let mapBroadcaster = (createBroadcaster) => (broadcaster) => (listener) => {
      broadcaster((value) => {
        let newBroadcaster = createBroadcaster(value);
        newBroadcaster(listener);
      });
    };
    
    let hangmanLogic = (value) => {
      return map((letter) => (value.includes(letter) ? letter : "*"));
    };
    
    let applyOperator = (broadcaster) =>
      mapBroadcaster((operator) => operator(broadcaster));
    
    let stringConcat = (broadcaster) => (listener) => {
      let result = "";
      broadcaster((value) => {
        if (value === done) {
          listener(result);
          result = "";
          return;
        }
        result += value;
      });
    };
    
    let hangman = pipe(map(hangmanLogic), applyOperator(word), stringConcat);
    hangman(inputValue)(log);


    Full code:

    import { addListener, done, forOf } from "./broadcasters";
    import { targetValue, map } from "./operators";
    import { pipe } from "lodash/fp";
    const log = console.log;
    
    let inputInput = addListener("#input", "input");
    let inputValue = targetValue(inputInput);
    
    let word = forOf("honeycomb");
    
    inputValue((value) => {});
    
    let mapBroadcaster = (createBroadcaster) => (broadcaster) => (listener) => {
      broadcaster((value) => {
        let newBroadcaster = createBroadcaster(value);
        newBroadcaster(listener);
      });
    };
    
    let hangmanLogic = (value) => {
      return map((letter) => (value.includes(letter) ? letter : "*"));
    };
    
    let applyOperator = (broadcaster) =>
      mapBroadcaster((operator) => operator(broadcaster));
    
    let stringConcat = (broadcaster) => (listener) => {
      let result = "";
      broadcaster((value) => {
        if (value === done) {
          listener(result);
          result = "";
          return;
        }
        result += value;
      });
    };
    
    let hangman = pipe(map(hangmanLogic), applyOperator(word), stringConcat);
    hangman(inputValue)(log);
  • 相关阅读:
    SharePoint Development
    win32- copyfile的使用
    SetWindowHookEx的复习
    C++ vector的使用
    关于char * 和 char [] 的一点理解
    CreateThread
    C++字符串大写字母转小写字母
    字符串逆序
    使用RegSetValueEx创建键值
    EnumColorProfiles WcsGetDefaultColorProfile WcsSetDefaultColorProfile的使用
  • 原文地址:https://www.cnblogs.com/Answer1215/p/13964352.html
Copyright © 2020-2023  润新知