问:
How do I integrate a game in my flutter app?
I want to use this game https://github.com/yum650350/tissuebox in my Flutter project. I tried calling different parts of the main page but it wasn't coming up properly even though the game itself is working.
I want to integrate it in my iOS app and want to call it with a
function which opens a separate page where the user can play the game.
Is there a way I can do it?
So this is what I tried:
I called the method of the game in a separate screen

```<code>import 'package:flutter/material.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  runApp(new MaterialApp(
    debugShowCheckedModeBanner: false,
    home: FirstScreen(),
  ));
}

class FirstScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('First Screen'),
      ),
      body: Center(
        child: RaisedButton(
          color: Colors.red,
          child: Text('Go to Second Screen'),
          onPressed: () {

            Navigator.of(context)
                .push(MaterialPageRoute<Null>(builder: (BuildContext context) {
           **???**
            }));
          },
        ),
      ),
    );
  }
}
</code>```

But I don't know what to call in ?? this part since the game isn't wrapped in any class. This is the code of the game I want to call.

```<code>import 'package:shared_preferences/shared_preferences.dart';
import 'package:audioplayers/audioplayers.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter/gestures.dart';
import 'package:flame/sprite.dart';
import 'package:flame/flame.dart';
import 'package:flame/util.dart';
import 'package:flame/game.dart';
import 'dart:math';

tissuemain() async {
  var util = Util();
  await util.fullScreen();
  await util.setOrientation(DeviceOrientation.portraitUp);
  //loadimages
  //tissuebox : 0,1,2,3,4,5,6
  //background : b
  //crown : c
  //tissue : t
  await Flame.images.loadAll(['b', '0', '1', '2', '3', '4', '5', '6', 't', 'c']);
  audioLoad(c) async => (await Flame.audio.load(c)).path;
  setAudio(a, s, v) async {
    await a.setUrl(await audioLoad(s), isLocal: true);
    a.setVolume(v);
  }
  //audios
  //single drag : s.mp3
  //double drag : s.mp3
  //triple drag ： s.mp3
  //tick tock : tk.mp3
  //game over : a.mp3
  GameTable.setAudioList(GameTable.audioList1, await audioLoad('s.mp3'));
  GameTable.setAudioList(GameTable.audioList2, await audioLoad('d.mp3'));
  GameTable.setAudioList(GameTable.audioList3, await audioLoad('t.mp3'));
  await setAudio(GameTable.tickTock, 'tk.mp3', 1.0);
  await setAudio(GameTable.gameOver, 'a.mp3', .5);
  var game = GameTable((await SharedPreferences.getInstance()).getInt('hs') ?? 0);
  var hDrag = HorizontalDragGestureRecognizer();
  var vDrag = VerticalDragGestureRecognizer();
  hDrag.onUpdate = game.onDragUpdate;
  hDrag.onStart = game.onDragStart;
  hDrag.onEnd = game.onDragEnd;
  vDrag.onUpdate = game.onDragUpdate;
  vDrag.onStart = game.onDragStart;
  vDrag.onEnd = game.onDragEnd;
  runApp(game.widget);
  util.addGestureRecognizer(hDrag);
  util.addGestureRecognizer(vDrag);
}

enum Drag { tissue, box, none }

class GameTable extends Game {
  //Audio
  //These are workarounds for the ios memory leak
  static var
      tickTock = AudioPlayer(),
      gameOver = AudioPlayer(),
      audioList1 = [AudioPlayer(), AudioPlayer(), AudioPlayer()],
      audioList2 = [AudioPlayer(), AudioPlayer()],
      audioList3 = [AudioPlayer(), AudioPlayer()],
      audioIndex1 = 0,
      audioIndex2 = 0,
      audioIndex3 = 0;
  static getPlayIndex(int audioPlayer) {
    if (audioPlayer == 1)
      audioIndex1 = audioIndex1 < audioList1.length - 1 ? audioIndex1 + 1 : 0;
    else if (audioPlayer == 2)
      audioIndex2 = audioIndex2 < audioList2.length - 1 ? audioIndex2 + 1 : 0;
    else if (audioPlayer == 3) audioIndex3 = audioIndex3 < audioList3.length - 1 ? audioIndex3 + 1 : 0;
    return audioPlayer == 1 ? audioIndex1 : audioPlayer == 2 ? audioIndex2 : audioIndex3;
  }
  static get tissue1 => audioList1[getPlayIndex(1)];
  static get tissue2 => audioList2[getPlayIndex(2)];
  static get tissue3 => audioList3[getPlayIndex(3)];
  static setAudioList(List<AudioPlayer> al,String audioName) => al.forEach((x) {
        x.setUrl(audioName, isLocal: true);
        x.setVolume(.2);
      });
  //

  var background = Sprite('b'),
      crown = Sprite('c'),
      initialPoint = Offset.zero,
      destPoint = Offset.zero,
      dragState = Drag.none,
      gameing = false,
      gameover = false,
      timePass = .0,
      heighScore = 0,
      score = 0,
      timePassTemp = 0;

  double tileSize, point1;
  double get k => screenSize.width / 5 / tileSize;
  Size screenSize;
  Rect rect;
  TissueBox tissueBox;

  saveHighScore() async => await (await SharedPreferences.getInstance()).setInt('hs', heighScore);

  GameTable(this.heighScore) {
    init();
  }

  init() async {
    resize(await Flame.util.initialDimensions());
    rect = Rect.fromLTWH(.0, screenSize.height - tileSize * 23, tileSize * 9, tileSize * 23);
    tissueBox = TissueBox(this);
  }

  @override
  render(Canvas c) {
    paintText(txt, offset, center, fontSize) {
      var painter = TextPainter(
          text: TextSpan(
              style: TextStyle(
                  color: Colors.white,
                  fontSize: fontSize,
                  fontFamily: 'NS'),
              text: txt),
          textScaleFactor: k,
          textDirection: TextDirection.ltr);
      painter.layout();
      painter.paint(c, center ? Offset(offset.dx - painter.width / 2, offset.dy) : offset);
    }

    background.renderRect(c, rect);
    tissueBox.render(c);
    var horCenter = tissueBox.initialLeft + tissueBox.boxRect.width / 2;
    if (gameing)
      paintText(timePass.toStringAsFixed(timePass < 1 ? 1 : 0) + 's', Offset(horCenter + 8, k * 23), true, k * 10);
    var heighScoreTxt = heighScore.toString();
    paintText(heighScoreTxt, Offset(heighScoreTxt.length==1?44.0:heighScoreTxt.length>2?22.0:33.0, k * 30), false, k * 12);
    crown.renderRect(c, Rect.fromLTWH(28.0, k * 10, 49.2, 39.0));
    paintText(score.toString(), Offset(horCenter, k * 50), true, k * 25);
    heighScore = score > heighScore ? score : heighScore;
  }

  @override
  update(double t) {
    tissueBox.update(t);
    timePass -= gameing || gameover ? t : 0;
    if (timePass < 0 && gameing) {
      tissueBox.isAway = true;
      gameing = false;
      timePass = 2;
      gameover = true;
      saveHighScore();
      tissueBox.newGame();
    } else if (gameing && !gameover) {
      var floor = timePass.floor();
      if (floor < timePassTemp && floor < 6 && floor != 0)
        TissueBox.delay(Duration(milliseconds: 300), () => GameTable.tickTock.resume());
      timePassTemp = floor;
    }
    gameover = timePass <= 0 && gameover ? false : gameover;
  }

  resize(s) {
    screenSize = s;
    tileSize = screenSize.width / 9;
  }

  onDragStart(DragStartDetails detail) {
    var point = detail.globalPosition;
    dragState = tissueBox.tissue.rect.contains(point) ? Drag.tissue : tissueBox.boxRect.contains(point) ? Drag.box : Drag.none;
    initialPoint = Offset(point.dx == 0 ? initialPoint.dx : point.dx, point.dy == 0 ? initialPoint.dy : point.dy);
    point1 = (tissueBox.tissue.rect.left - point.dx).abs();
  }

  onDragUpdate(DragUpdateDetails detail) {
    if (gameover || dragState == Drag.none) return;
    var point = detail.globalPosition;
    destPoint = Offset(point.dx == 0 ? destPoint.dx : point.dx, point.dy == 0 ? destPoint.dy : point.dy);
    if (dragState == Drag.tissue) {
      if (initialPoint.dy - destPoint.dy > 100) {
        if (gameing != true && gameover != true) {
          gameing = true;
          timePass = 10;
          score = 0;
        }
        var sub = (point1 - (tissueBox.tissue.rect.left - point.dx).abs()).abs();
        var addPoint = sub < 3 ? 3 : sub < 6 ? 2 : 1;
        dragState = Drag.none;
        tissueBox.nextTissue(addPoint);
        playTissueAudio(addPoint);
        score += addPoint;
      }
    } else if (dragState == Drag.box) {
      tissueBox.boxRect = Rect.fromLTWH(tissueBox.initialLeft + destPoint.dx - initialPoint.dx, tissueBox.boxRect.top, TissueBox.boxSize.dx, TissueBox.boxSize.dy);
      tissueBox.ismoving = true;
    }
  }

  playTissueAudio(i) => (i == 1 ? GameTable.tissue1 : i == 2 ? GameTable.tissue2 : GameTable.tissue3).resume();
  onDragEnd(DragEndDetails detail) {
    initialPoint = Offset.zero;
    dragState = Drag.none;
    tissueBox.tissue.isMoving = false;
    tissueBox.ismoving = false;
    destPoint = initialPoint;
  }
}

class TissueBox {
  Rect get initialRect => Rect.fromLTWH(boxRect.center.dx - Tissue.width / 2, boxRect.top - boxRect.height + 20.3, Tissue.width, Tissue.width);
  Sprite get getBoxSprite =>Sprite(  rnd.nextInt(7).toString());
  var tissueAwayList = List<TissueAway>(), rnd = Random(), ismoving = false, isAway = false;
  Offset get getTissueUpPosition => Offset(initialRect.left, initialRect.top - 150);
  final GameTable game;
  Sprite boxSprite;
  Rect boxRect;
  int tissueCount;
  Tissue tissue;
  double get initialLeft => game.screenSize.width / 2 - TissueBox.boxSize.dx / 2;
  double get initialTop => game.screenSize.height - game.tileSize * 5.5;
  static var boxSize = Offset(150.0, 100.0);
  TissueBox(this.game) {
    boxRect = Rect.fromLTWH(initialLeft, initialTop, boxSize.dx, boxSize.dy);
    tissueCount = 10 - rnd.nextInt(5);
    tissue = Tissue(game, this);
    boxSprite = getBoxSprite;
  }
  render(Canvas c) {
    boxSprite.renderRect(c, boxRect);
    tissue.render(c);
    tissueAwayList.forEach((x) => x.render(c));
  }

  update(double t) {
    tissue.update(t);
    tissueAwayList.removeWhere((x) => x.isAway);
    tissueAwayList.forEach((x) => x.update(t));
    var distense = boxRect.left - initialLeft;
    if (ismoving && !game.gameover) {
      if (distense.abs() > 50 && tissueCount == 0){
        isAway = true;
      }
    } else if (isAway && !game.gameover) {
      boxRect = boxRect.shift(Offset(distense > 0 ? boxRect.left + game.k * 11 : boxRect.left - game.k * 11, boxRect.top));
      if (boxRect.right < -50 || boxRect.left > game.screenSize.width + 50) {
        newBox();
      }
    } else if (isAway && game.gameover) {
      var target = Offset(boxRect.left, game.screenSize.height + Tissue.width) - Offset(boxRect.left, boxRect.top);
      boxRect = boxRect.shift(
        game.k * 11 < target.distance ?
            Offset.fromDirection(target.direction, game.k * 11)
          : target);
    } else {
      var target = Offset(initialLeft, initialTop) - Offset(boxRect.left, boxRect.top);
      boxRect = boxRect.shift(
        game.k * 11 < target.distance ?
          Offset.fromDirection(target.direction, game.k * 11)
          : target);
    }
  }

  nextTissue(int pointsAdd) {
    var duration = Duration(milliseconds: 100);
    tissueAwayList.add(TissueAway(game, this));
    if (pointsAdd > 1)
      delay(duration, () {
        tissueAwayList.add(TissueAway(game, this));
        if (pointsAdd > 2)
          delay(duration, () {
            tissueAwayList.add(TissueAway(game, this));
          });
      });
    tissue = Tissue(game, this, --tissueCount == 0);
  }

  newBox() {
    boxSprite = getBoxSprite;
    boxRect = Rect.fromLTWH(boxRect.right < -0 ? game.screenSize.width + 50 - boxSize.dx : -50.0, initialTop, boxSize.dx, boxSize.dy);
    tissueCount = 10 - rnd.nextInt(5);
    tissue = Tissue(game, this);
    isAway = false;
    ismoving = false;
  }

  newGame() async {
    isAway = true;
    GameTable.gameOver.resume();
    await delay(Duration(seconds: 2), () {});
    newBox();
  }

  static delay(duration, func()) async => await Future.delayed(duration, func);
}

class Tissue {
  var tissueSprite = Sprite('t'), isMoving = false;
  static var width = 100.0;
  final TissueBox tissueBox;
  final GameTable game;
  bool isAway;
  Rect rect;
  Tissue(this.game, this.tissueBox, [this.isAway = false]) {
    rect = tissueBox.initialRect;
  }
  render(Canvas c) => tissueSprite.renderRect(c, rect);
  update(double t) => rect = isAway ? rect.shift(Offset.infinite) : tissueBox.initialRect;
}

class TissueAway extends Tissue {
  TissueAway(GameTable game, TissueBox tissueBox) : super(game, tissueBox);
  render(Canvas c) => tissueSprite.renderRect(c, rect);
  update(double t) {
    var speed = 500 * t;
    Offset target = tissueBox.getTissueUpPosition - Offset(rect.left, rect.top);
    if (speed < target.distance)
      rect = rect.shift(Offset.fromDirection(target.direction, speed));
    else
      isAway = true;
  }
}
</code>```

答:
The code in the main method will have a line that says runApp(...). The value of the ... is a widget that will be treated as the root widget of the app. In theory, you could just take that widget and pass it to your Navigator.push method and it should treat that widget as any other widget.

That being said, real life probably won't be as clean as this. There might be some initialization code in that app's main method or root widget that won't work properly if the app has long since already been initialized. Since virtually every Flutter app's root widget creates a WidgetsApp (or one of its derived classes MaterialApp or CupertinoApp), there might be some conflict that arrives from having one of those widgets being inserted as a descendent of another one of those widgets.

The game in question may work simply, or it might take some tweaking to work properly. That's something that will depend entirely on what app you are trying to embed into your own, so the only solution is to try it out and see for yourself.

Body:
I want to use this game https://github.com/yum650350/tissuebox in my Flutter project. I tried calling different parts of the main page but it wasn't coming up properly even though the game itself is working.
I want to integrate it in my iOS app and want to call it with a
function which opens a separate page where the user can play the game.
Is there a way I can do it?
So this is what I tried:
I called the method of the game in a separate screen

import 'package:flutter/material.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  runApp(new MaterialApp(
    debugShowCheckedModeBanner: false,
    home: FirstScreen(),
  ));
}

class FirstScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('First Screen'),
      ),
      body: Center(
        child: RaisedButton(
          color: Colors.red,
          child: Text('Go to Second Screen'),
          onPressed: () {

            Navigator.of(context)
                .push(MaterialPageRoute<Null>(builder: (BuildContext context) {
           **???**
            }));
          },
        ),
      ),
    );
  }
}

But I don't know what to call in ?? this part since the game isn't wrapped in any class. This is the code of the game I want to call.

import 'package:shared_preferences/shared_preferences.dart';
import 'package:audioplayers/audioplayers.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter/gestures.dart';
import 'package:flame/sprite.dart';
import 'package:flame/flame.dart';
import 'package:flame/util.dart';
import 'package:flame/game.dart';
import 'dart:math';

tissuemain() async {
  var util = Util();
  await util.fullScreen();
  await util.setOrientation(DeviceOrientation.portraitUp);
  //loadimages
  //tissuebox : 0,1,2,3,4,5,6
  //background : b
  //crown : c
  //tissue : t
  await Flame.images.loadAll(['b', '0', '1', '2', '3', '4', '5', '6', 't', 'c']);
  audioLoad(c) async => (await Flame.audio.load(c)).path;
  setAudio(a, s, v) async {
    await a.setUrl(await audioLoad(s), isLocal: true);
    a.setVolume(v);
  }
  //audios
  //single drag : s.mp3
  //double drag : s.mp3
  //triple drag ： s.mp3
  //tick tock : tk.mp3
  //game over : a.mp3
  GameTable.setAudioList(GameTable.audioList1, await audioLoad('s.mp3'));
  GameTable.setAudioList(GameTable.audioList2, await audioLoad('d.mp3'));
  GameTable.setAudioList(GameTable.audioList3, await audioLoad('t.mp3'));
  await setAudio(GameTable.tickTock, 'tk.mp3', 1.0);
  await setAudio(GameTable.gameOver, 'a.mp3', .5);
  var game = GameTable((await SharedPreferences.getInstance()).getInt('hs') ?? 0);
  var hDrag = HorizontalDragGestureRecognizer();
  var vDrag = VerticalDragGestureRecognizer();
  hDrag.onUpdate = game.onDragUpdate;
  hDrag.onStart = game.onDragStart;
  hDrag.onEnd = game.onDragEnd;
  vDrag.onUpdate = game.onDragUpdate;
  vDrag.onStart = game.onDragStart;
  vDrag.onEnd = game.onDragEnd;
  runApp(game.widget);
  util.addGestureRecognizer(hDrag);
  util.addGestureRecognizer(vDrag);
}

enum Drag { tissue, box, none }

class GameTable extends Game {
  //Audio
  //These are workarounds for the ios memory leak
  static var
      tickTock = AudioPlayer(),
      gameOver = AudioPlayer(),
      audioList1 = [AudioPlayer(), AudioPlayer(), AudioPlayer()],
      audioList2 = [AudioPlayer(), AudioPlayer()],
      audioList3 = [AudioPlayer(), AudioPlayer()],
      audioIndex1 = 0,
      audioIndex2 = 0,
      audioIndex3 = 0;
  static getPlayIndex(int audioPlayer) {
    if (audioPlayer == 1)
      audioIndex1 = audioIndex1 < audioList1.length - 1 ? audioIndex1 + 1 : 0;
    else if (audioPlayer == 2)
      audioIndex2 = audioIndex2 < audioList2.length - 1 ? audioIndex2 + 1 : 0;
    else if (audioPlayer == 3) audioIndex3 = audioIndex3 < audioList3.length - 1 ? audioIndex3 + 1 : 0;
    return audioPlayer == 1 ? audioIndex1 : audioPlayer == 2 ? audioIndex2 : audioIndex3;
  }
  static get tissue1 => audioList1[getPlayIndex(1)];
  static get tissue2 => audioList2[getPlayIndex(2)];
  static get tissue3 => audioList3[getPlayIndex(3)];
  static setAudioList(List<AudioPlayer> al,String audioName) => al.forEach((x) {
        x.setUrl(audioName, isLocal: true);
        x.setVolume(.2);
      });
  //

  var background = Sprite('b'),
      crown = Sprite('c'),
      initialPoint = Offset.zero,
      destPoint = Offset.zero,
      dragState = Drag.none,
      gameing = false,
      gameover = false,
      timePass = .0,
      heighScore = 0,
      score = 0,
      timePassTemp = 0;

  double tileSize, point1;
  double get k => screenSize.width / 5 / tileSize;
  Size screenSize;
  Rect rect;
  TissueBox tissueBox;

  saveHighScore() async => await (await SharedPreferences.getInstance()).setInt('hs', heighScore);

  GameTable(this.heighScore) {
    init();
  }

  init() async {
    resize(await Flame.util.initialDimensions());
    rect = Rect.fromLTWH(.0, screenSize.height - tileSize * 23, tileSize * 9, tileSize * 23);
    tissueBox = TissueBox(this);
  }

  @override
  render(Canvas c) {
    paintText(txt, offset, center, fontSize) {
      var painter = TextPainter(
          text: TextSpan(
              style: TextStyle(
                  color: Colors.white,
                  fontSize: fontSize,
                  fontFamily: 'NS'),
              text: txt),
          textScaleFactor: k,
          textDirection: TextDirection.ltr);
      painter.layout();
      painter.paint(c, center ? Offset(offset.dx - painter.width / 2, offset.dy) : offset);
    }

    background.renderRect(c, rect);
    tissueBox.render(c);
    var horCenter = tissueBox.initialLeft + tissueBox.boxRect.width / 2;
    if (gameing)
      paintText(timePass.toStringAsFixed(timePass < 1 ? 1 : 0) + 's', Offset(horCenter + 8, k * 23), true, k * 10);
    var heighScoreTxt = heighScore.toString();
    paintText(heighScoreTxt, Offset(heighScoreTxt.length==1?44.0:heighScoreTxt.length>2?22.0:33.0, k * 30), false, k * 12);
    crown.renderRect(c, Rect.fromLTWH(28.0, k * 10, 49.2, 39.0));
    paintText(score.toString(), Offset(horCenter, k * 50), true, k * 25);
    heighScore = score > heighScore ? score : heighScore;
  }

  @override
  update(double t) {
    tissueBox.update(t);
    timePass -= gameing || gameover ? t : 0;
    if (timePass < 0 && gameing) {
      tissueBox.isAway = true;
      gameing = false;
      timePass = 2;
      gameover = true;
      saveHighScore();
      tissueBox.newGame();
    } else if (gameing && !gameover) {
      var floor = timePass.floor();
      if (floor < timePassTemp && floor < 6 && floor != 0)
        TissueBox.delay(Duration(milliseconds: 300), () => GameTable.tickTock.resume());
      timePassTemp = floor;
    }
    gameover = timePass <= 0 && gameover ? false : gameover;
  }

  resize(s) {
    screenSize = s;
    tileSize = screenSize.width / 9;
  }

  onDragStart(DragStartDetails detail) {
    var point = detail.globalPosition;
    dragState = tissueBox.tissue.rect.contains(point) ? Drag.tissue : tissueBox.boxRect.contains(point) ? Drag.box : Drag.none;
    initialPoint = Offset(point.dx == 0 ? initialPoint.dx : point.dx, point.dy == 0 ? initialPoint.dy : point.dy);
    point1 = (tissueBox.tissue.rect.left - point.dx).abs();
  }

  onDragUpdate(DragUpdateDetails detail) {
    if (gameover || dragState == Drag.none) return;
    var point = detail.globalPosition;
    destPoint = Offset(point.dx == 0 ? destPoint.dx : point.dx, point.dy == 0 ? destPoint.dy : point.dy);
    if (dragState == Drag.tissue) {
      if (initialPoint.dy - destPoint.dy > 100) {
        if (gameing != true && gameover != true) {
          gameing = true;
          timePass = 10;
          score = 0;
        }
        var sub = (point1 - (tissueBox.tissue.rect.left - point.dx).abs()).abs();
        var addPoint = sub < 3 ? 3 : sub < 6 ? 2 : 1;
        dragState = Drag.none;
        tissueBox.nextTissue(addPoint);
        playTissueAudio(addPoint);
        score += addPoint;
      }
    } else if (dragState == Drag.box) {
      tissueBox.boxRect = Rect.fromLTWH(tissueBox.initialLeft + destPoint.dx - initialPoint.dx, tissueBox.boxRect.top, TissueBox.boxSize.dx, TissueBox.boxSize.dy);
      tissueBox.ismoving = true;
    }
  }

  playTissueAudio(i) => (i == 1 ? GameTable.tissue1 : i == 2 ? GameTable.tissue2 : GameTable.tissue3).resume();
  onDragEnd(DragEndDetails detail) {
    initialPoint = Offset.zero;
    dragState = Drag.none;
    tissueBox.tissue.isMoving = false;
    tissueBox.ismoving = false;
    destPoint = initialPoint;
  }
}

class TissueBox {
  Rect get initialRect => Rect.fromLTWH(boxRect.center.dx - Tissue.width / 2, boxRect.top - boxRect.height + 20.3, Tissue.width, Tissue.width);
  Sprite get getBoxSprite =>Sprite(  rnd.nextInt(7).toString());
  var tissueAwayList = List<TissueAway>(), rnd = Random(), ismoving = false, isAway = false;
  Offset get getTissueUpPosition => Offset(initialRect.left, initialRect.top - 150);
  final GameTable game;
  Sprite boxSprite;
  Rect boxRect;
  int tissueCount;
  Tissue tissue;
  double get initialLeft => game.screenSize.width / 2 - TissueBox.boxSize.dx / 2;
  double get initialTop => game.screenSize.height - game.tileSize * 5.5;
  static var boxSize = Offset(150.0, 100.0);
  TissueBox(this.game) {
    boxRect = Rect.fromLTWH(initialLeft, initialTop, boxSize.dx, boxSize.dy);
    tissueCount = 10 - rnd.nextInt(5);
    tissue = Tissue(game, this);
    boxSprite = getBoxSprite;
  }
  render(Canvas c) {
    boxSprite.renderRect(c, boxRect);
    tissue.render(c);
    tissueAwayList.forEach((x) => x.render(c));
  }

  update(double t) {
    tissue.update(t);
    tissueAwayList.removeWhere((x) => x.isAway);
    tissueAwayList.forEach((x) => x.update(t));
    var distense = boxRect.left - initialLeft;
    if (ismoving && !game.gameover) {
      if (distense.abs() > 50 && tissueCount == 0){
        isAway = true;
      }
    } else if (isAway && !game.gameover) {
      boxRect = boxRect.shift(Offset(distense > 0 ? boxRect.left + game.k * 11 : boxRect.left - game.k * 11, boxRect.top));
      if (boxRect.right < -50 || boxRect.left > game.screenSize.width + 50) {
        newBox();
      }
    } else if (isAway && game.gameover) {
      var target = Offset(boxRect.left, game.screenSize.height + Tissue.width) - Offset(boxRect.left, boxRect.top);
      boxRect = boxRect.shift(
        game.k * 11 < target.distance ?
            Offset.fromDirection(target.direction, game.k * 11)
          : target);
    } else {
      var target = Offset(initialLeft, initialTop) - Offset(boxRect.left, boxRect.top);
      boxRect = boxRect.shift(
        game.k * 11 < target.distance ?
          Offset.fromDirection(target.direction, game.k * 11)
          : target);
    }
  }

  nextTissue(int pointsAdd) {
    var duration = Duration(milliseconds: 100);
    tissueAwayList.add(TissueAway(game, this));
    if (pointsAdd > 1)
      delay(duration, () {
        tissueAwayList.add(TissueAway(game, this));
        if (pointsAdd > 2)
          delay(duration, () {
            tissueAwayList.add(TissueAway(game, this));
          });
      });
    tissue = Tissue(game, this, --tissueCount == 0);
  }

  newBox() {
    boxSprite = getBoxSprite;
    boxRect = Rect.fromLTWH(boxRect.right < -0 ? game.screenSize.width + 50 - boxSize.dx : -50.0, initialTop, boxSize.dx, boxSize.dy);
    tissueCount = 10 - rnd.nextInt(5);
    tissue = Tissue(game, this);
    isAway = false;
    ismoving = false;
  }

  newGame() async {
    isAway = true;
    GameTable.gameOver.resume();
    await delay(Duration(seconds: 2), () {});
    newBox();
  }

  static delay(duration, func()) async => await Future.delayed(duration, func);
}

class Tissue {
  var tissueSprite = Sprite('t'), isMoving = false;
  static var width = 100.0;
  final TissueBox tissueBox;
  final GameTable game;
  bool isAway;
  Rect rect;
  Tissue(this.game, this.tissueBox, [this.isAway = false]) {
    rect = tissueBox.initialRect;
  }
  render(Canvas c) => tissueSprite.renderRect(c, rect);
  update(double t) => rect = isAway ? rect.shift(Offset.infinite) : tissueBox.initialRect;
}

class TissueAway extends Tissue {
  TissueAway(GameTable game, TissueBox tissueBox) : super(game, tissueBox);
  render(Canvas c) => tissueSprite.renderRect(c, rect);
  update(double t) {
    var speed = 500 * t;
    Offset target = tissueBox.getTissueUpPosition - Offset(rect.left, rect.top);
    if (speed < target.distance)
      rect = rect.shift(Offset.fromDirection(target.direction, speed));
    else
      isAway = true;
  }
}


来源: stackexchange

问:
Sendkeys("{BACKSPACE}") inserts "B" characters instead of backspacing
I have a TextBox declared in a Silverlight project with contents “123456” and then use the following code in a Coded UI test.  First it searches and clicks the TextBox to set focus, and then tries to delete characters.

```<code>currencyPage.ClickEditByAutomationId("textBox");
Keyboard.SendKeys("{END}");
Keyboard.SendKeys("{BACKSPACE}");
Keyboard.SendKeys("{BACKSPACE}");
Keyboard.SendKeys("{BACKSPACE}");
Keyboard.SendKeys("{BACKSPACE}");
Keyboard.SendKeys("{BACKSPACE}");
</code>```

This is the resulting text in my TextBox: 123456BBBBB

What am I doing wrong?  XAML of the textbox:

答: Try Keyboard.SendKeys(@"{BACKSPACE}"); or Keyboard.SendKeys("{{BACKSPACE}}");

ContentLicense: CC BY-SA 3.0

Body:
I have a TextBox declared in a Silverlight project with contents “123456” and then use the following code in a Coded UI test.  First it searches and clicks the TextBox to set focus, and then tries to delete characters.

currencyPage.ClickEditByAutomationId("textBox");
Keyboard.SendKeys("{END}");
Keyboard.SendKeys("{BACKSPACE}");
Keyboard.SendKeys("{BACKSPACE}");
Keyboard.SendKeys("{BACKSPACE}");
Keyboard.SendKeys("{BACKSPACE}");
Keyboard.SendKeys("{BACKSPACE}");

This is the resulting text in my TextBox: 123456BBBBB

What am I doing wrong?  XAML of the textbox:


问:
Elixir - Call method on module by String-name
I'm pretty new to Elixir and functional programming-languages in general.

In Elixir, I want to call one specific function on Modules, given the Module name as String.

I've got the following (very bad) code working, which pretty much does what I want to:

```<code>module_name = elem(elem(Code.eval_file("module.ex", __DIR__), 0), 1)
apply(module_name, :helloWorld, [])
</code>```

This (at least as I understand it) compiles the (already compiled) module of module.ex in the current directory. I'm extracting the modules name (not as a String, don't know what data-type it actually is) out of the two tuples and run the method helloWorld on it.

There are two problems with this code:

It prints a warning like redefining module Balance. I certainly don't want that to happen in production.

AFAIK this code compiles module.ex. But as module.ex is already compiled and loaded, it don't want that to happen.

I don't need to call methods on these modules by filename, the module-name would be ok too. But it does have to by dynamic, eg. entering "Book" at the command line should, after a check whether the module exists, call the function Book.helloWorld.

Thanks.

答:
Here is a simple explanation:

Assuming that you have a module like this:

```<code>defmodule MyNamespace.Printer do
  def print_hello(name) do
    IO.puts("Hello, #{name}!")
  end
end
</code>```

Then you have a string that hold the module name that you can pass around in your application like this:

```<code>module_name = "Elixir.MyNamespace.Printer"
</code>```

Whenever you receive the string module_name, you can instantiate a module and call functions on the module like this:

```<code>module = String.to_existing_atom(module_name)
module.print_hello("John")
</code>```

It will print:

```<code>Hello, John!
</code>```

Another way to dynamically call the function MyNamespace.Printer.print_hello/1 is:

```<code>print_hello_func = &module.print_hello/1
print_hello_func.("Jane")
</code>```

It will print:

```<code>Hello, Jane!
</code>```

Or if you want to have both module_name as atom and function_name as atom, and pass them around to be executed somewhere, you can write something like this:

```<code>a_module_name = :"Elixir.MyNamespace.Printer"
a_function_name = :print_hello
</code>```

Then whenever you have a_module_name and a_function_name as atoms, you can call like this:

```<code>apply(a_module_name, a_function_name, ["Jackie"])
</code>```

It will print

```<code>Hello, Jackie!
</code>```

Of course you can pass module_name and function_name as strings and convert them to atoms later. Or you can pass module name as atom and function as a reference to function.

Body:
I'm pretty new to Elixir and functional programming-languages in general.

In Elixir, I want to call one specific function on Modules, given the Module name as String.

I've got the following (very bad) code working, which pretty much does what I want to:

module_name = elem(elem(Code.eval_file("module.ex", __DIR__), 0), 1)
apply(module_name, :helloWorld, [])

This (at least as I understand it) compiles the (already compiled) module of module.ex in the current directory. I'm extracting the modules name (not as a String, don't know what data-type it actually is) out of the two tuples and run the method helloWorld on it.

There are two problems with this code:

It prints a warning like redefining module Balance. I certainly don't want that to happen in production.

AFAIK this code compiles module.ex. But as module.ex is already compiled and loaded, it don't want that to happen.

I don't need to call methods on these modules by filename, the module-name would be ok too. But it does have to by dynamic, eg. entering "Book" at the command line should, after a check whether the module exists, call the function Book.helloWorld.

Thanks.

Body:
Here is a simple explanation:

Assuming that you have a module like this:

defmodule MyNamespace.Printer do
  def print_hello(name) do
    IO.puts("Hello, #{name}!")
  end
end

Then you have a string that hold the module name that you can pass around in your application like this:

module_name = "Elixir.MyNamespace.Printer"

Whenever you receive the string module_name, you can instantiate a module and call functions on the module like this:

module = String.to_existing_atom(module_name)
module.print_hello("John")

It will print:

Hello, John!

Another way to dynamically call the function MyNamespace.Printer.print_hello/1 is:

print_hello_func = &module.print_hello/1
print_hello_func.("Jane")

It will print:

Hello, Jane!

Or if you want to have both module_name as atom and function_name as atom, and pass them around to be executed somewhere, you can write something like this:

a_module_name = :"Elixir.MyNamespace.Printer"
a_function_name = :print_hello

Then whenever you have a_module_name and a_function_name as atoms, you can call like this:

apply(a_module_name, a_function_name, ["Jackie"])

It will print

Hello, Jackie!

Of course you can pass module_name and function_name as strings and convert them to atoms later. Or you can pass module name as atom and function as a reference to function.

ContentLicense: CC BY-SA 4.0


问:
How to prevent backend calls when opening static subpages?
I have a project with a separated backend and frontend. Every time I try to open any other page than homepage, the JHipster fires and waits for two requests:

API_URL/jhb/management/info

API_URL/jhb/api/account

I have pages with static content that do not need connection with the server. Sometimes I am disconnected from the server, but the app always makes the calls, then waits and shows the page only after certain timeout (about 5 seconds). However, it does not wait when I try to open the homepage.

Is there a way to tell JHipster to skip or don't wait for these two backend calls, at least for certain routes?

I don't use microservices, just regular Tomcat deployment. JHipster version 6.5.1, Angular frontend

答:
My solution to the problem was to completely remove canActivate: [UserRouteAccessService] property from the Route. Then, the static page is, as wanted, visible immediately and for everyone.

It works, but what I was looking for was enabling (displaying) navbar/footer before (component's) route access was checked. Probably creating a nested component would do the trick. If you know a better solution /have better idea please share!


问:
Module 'pytextrank' has no attribute 'parse_doc'
I am performing a nlp task. I have written the following code. While executing, it is showing the following error. Any suggestion to resolve the error will be helpful. I am having python 3 env in google colab .

```<code># Pytextrank
import pytextrank
import json

# Sample text
sample_text = 'I Like Flipkart. He likes Amazone. she likes Snapdeal. Flipkart and amazone is on top of google search.'

# Create dictionary to feed into json file

file_dic = {"id" : 0,"text" : sample_text}
file_dic = json.dumps(file_dic)
loaded_file_dic = json.loads(file_dic)

# Create test.json and feed file_dic into it.
with open('test.json', 'w') as outfile:
json.dump(loaded_file_dic, outfile)

path_stage0 = "test.json"
path_stage1 = "o1.json"

# Extract keyword using pytextrank
with open(path_stage1, 'w') as f:
for graf in pytextrank.parse_doc(pytextrank.json_iter(path_stage0)):
f.write("%s\n" % pytextrank.pretty_print(graf._asdict()))

print(pytextrank.pretty_print(graf._asdict()))
</code>```

I am getting the following error :

```<code>  AttributeError                            Traceback (most recent call last)
  <ipython-input-33-286ce104df34> in <module>()
       20 # Extract keyword using pytextrank
       21 with open(path_stage1, 'w') as f:
  ---> 22   for graf in
  pytextrank.parse_doc(pytextrank.json_iter(path_stage0)):
       23     f.write("%s\n" % pytextrank.pretty_print(graf._asdict()))
       24     print(pytextrank.pretty_print(graf._asdict()))

      AttributeError: module 'pytextrank' has no attribute 'parse_doc'
</code>```

答:
There's a newer release of PyTextRank which simplifies the calling code, and makes these steps unnecessary:
https://spacy.io/universe/project/spacy-pytextrank</p>

Body:
I am performing a nlp task. I have written the following code. While executing, it is showing the following error. Any suggestion to resolve the error will be helpful. I am having python 3 env in google colab .

# Pytextrank
import pytextrank
import json

# Sample text
sample_text = 'I Like Flipkart. He likes Amazone. she likes Snapdeal. Flipkart and amazone is on top of google search.'

# Create dictionary to feed into json file

file_dic = {"id" : 0,"text" : sample_text}
file_dic = json.dumps(file_dic)
loaded_file_dic = json.loads(file_dic)

# Create test.json and feed file_dic into it.
with open('test.json', 'w') as outfile:
json.dump(loaded_file_dic, outfile)

path_stage0 = "test.json"
path_stage1 = "o1.json"

# Extract keyword using pytextrank
with open(path_stage1, 'w') as f:
for graf in pytextrank.parse_doc(pytextrank.json_iter(path_stage0)):
f.write("%s\n" % pytextrank.pretty_print(graf._asdict()))

print(pytextrank.pretty_print(graf._asdict()))

I am getting the following error :

  AttributeError                            Traceback (most recent call last)
  <ipython-input-33-286ce104df34> in <module>()
       20 # Extract keyword using pytextrank
       21 with open(path_stage1, 'w') as f:
  ---> 22   for graf in
  pytextrank.parse_doc(pytextrank.json_iter(path_stage0)):
       23     f.write("%s\n" % pytextrank.pretty_print(graf._asdict()))
       24     print(pytextrank.pretty_print(graf._asdict()))

      AttributeError: module 'pytextrank' has no attribute 'parse_doc'


问:
How to identify Redis keys from Redis-cli monitor command?
Possibly related to - Redis command to get all available keys?

I have a Redis server storing SixPack data (https://github.com/sixpack/sixpack - a framework to enable A/B testing). I can monitor the Redis server and see the following sample entries when I run monitor command:

```<code>$ redis-cli monitor|grep 'TEST'
</code>```

I can see that there are several keys being used/set. I am attaching a sample below:

```<code>1581720438.878978 [15 127.0.0.1:39722] "GETBIT" "sixpack:e:-28591_:excluded" "2307"
1581720439.623866 [15 127.0.0.1:39722] "LRANGE" "sixpack:e:-28003_:alternatives" "0" "-1"
1581720439.624209 [15 127.0.0.1:39722] "HGET" "sixpack:e:-28003_" "traffic_fraction"
1581720439.624557 [15 127.0.0.1:39722] "GET" "sixpack:e:-28003_:winner"
1581720439.624822 [15 127.0.0.1:39722] "HEXISTS" "sixpack:e:-28003_" "archived"
1581720439.625110 [15 127.0.0.1:39722] "EVALSHA" "bcbf3b3ac336a33c2cd7ad0e1fca28db7b49fdee" "1" "sixpack:e:-28003_Recapture:users" "ac945bf7-285e-4f69-83fd-1336e084a318"
</code>```

However, when I try to access the keys by running $ redis-cli KEYS '*' command, I only get an empty list (empty list or set).

Updated: I checked that this is not a cluster setup. I also check the DBSIZE command. It returns 0.

How can I derive the keys from the MONITOR output? Is there a way to get all the keys in a Redis CLI?

答:
The appropriate database index should be used when running the KEYS command if more than one Redis database is in use.

```<code>$redis-cli -n <DB number> KEYS '*' # or use --scan
</code>```

Redis comes with 16 default 'databases' which can be used to split the keys up. To use them from the tool, redis-cli -n 2 to start using the 3rd DB (the default is 0). Once inside the tool, or from the API, there is the SELECT 2 command (again, to select the db to use).  More can be allowed for - it's just a number in the redis.conf file.

The Sixpack A/B testing tool configuration has two methods to be able to choose which Redis database to use - in the configuration is the key (eg)  redis_db: 15, or it, and more can be set by environment variable: SIXPACK_CONFIG_REDIS_DB, along with _PORT, _HOST, _PASSWORD & _PREFIX.

Body:
Possibly related to - Redis command to get all available keys?

I have a Redis server storing SixPack data (https://github.com/sixpack/sixpack - a framework to enable A/B testing). I can monitor the Redis server and see the following sample entries when I run monitor command:

$ redis-cli monitor|grep 'TEST'

I can see that there are several keys being used/set. I am attaching a sample below:

1581720438.878978 [15 127.0.0.1:39722] "GETBIT" "sixpack:e:-28591_:excluded" "2307"
1581720439.623866 [15 127.0.0.1:39722] "LRANGE" "sixpack:e:-28003_:alternatives" "0" "-1"
1581720439.624209 [15 127.0.0.1:39722] "HGET" "sixpack:e:-28003_" "traffic_fraction"
1581720439.624557 [15 127.0.0.1:39722] "GET" "sixpack:e:-28003_:winner"
1581720439.624822 [15 127.0.0.1:39722] "HEXISTS" "sixpack:e:-28003_" "archived"
1581720439.625110 [15 127.0.0.1:39722] "EVALSHA" "bcbf3b3ac336a33c2cd7ad0e1fca28db7b49fdee" "1" "sixpack:e:-28003_Recapture:users" "ac945bf7-285e-4f69-83fd-1336e084a318"

However, when I try to access the keys by running $ redis-cli KEYS '*' command, I only get an empty list (empty list or set).

Updated: I checked that this is not a cluster setup. I also check the DBSIZE command. It returns 0.

How can I derive the keys from the MONITOR output? Is there a way to get all the keys in a Redis CLI?

Body:
The appropriate database index should be used when running the KEYS command if more than one Redis database is in use.

$redis-cli -n <DB number> KEYS '*' # or use --scan

Redis comes with 16 default 'databases' which can be used to split the keys up. To use them from the tool, redis-cli -n 2 to start using the 3rd DB (the default is 0). Once inside the tool, or from the API, there is the SELECT 2 command (again, to select the db to use).  More can be allowed for - it's just a number in the redis.conf file.

The Sixpack A/B testing tool configuration has two methods to be able to choose which Redis database to use - in the configuration is the key (eg)  redis_db: 15, or it, and more can be set by environment variable: SIXPACK_CONFIG_REDIS_DB, along with _PORT, _HOST, _PASSWORD & _PREFIX.


问:
Which Gamelift instance should I use to handle 1 million players concurrently?
I am trying to understand how Gamelift works as I am totally a novice in Game development.

According to AWS, a Gamelift instance can handle up to 200 players per session but can also host several session in the same time.

Firstly, I'd like to know, for instance, can a m5.large instance can handle a 200 players sessions ?

Secondly, Which instance offer the largest capacity to host multiple sessions simultaneously/concurrently ?

Thirdly, What is the difference between Linux and Windows instances ? I know Windows instances are way more expensive but what are the advantages ?

Thanks

答:
GameLift is simply a provisioning service for machines to run a game server. The game server must already be developed. If you want to run a Counter-Strike: Go tournament, you can spin up servers for all tournament players on GameLift instances, for example. (Assuming software licensing all works out correctly and you have an adapted version of the game server.)

Similarly, if you're a game developer who wants to run dedicated servers, you can develop your own server software, and run on GameLift instances. Or any other virtual hosting solution, really. The main thing you get with GameLift is that they seem to have built/configured the servers to be "real time," as in, the virtualization platform causes smaller stalls because of "noisy neighbors" problems. A regular small EC2 instance can go away for dozens of milliseconds or even a second at a time, and just gives you an "average" throughput over time. Game servers need to not go away for long times, because then you will "miss a step" and cause lag for all connected players. On a physical server, this is less of a problem, as there is no hypervisor trying to schedule time between different guest instances.

Thus, "how many players can I run on an instance" depends entirely on how your server is implemented.


问:
Check my Kafka and Zookeeper functionality and connections
As part of my system, I need to use Kafka and Zookeeper cluster on top of Kubernetes.
I'm using Statefulset for deploying them and use headless service for Kafka's Broker to be able to talk with the Zookeeper servers.

Its seems that the clusters are running - (by typing kubectl get pods)

```<code>NAME                      READY   STATUS    RESTARTS   AGE
kafka-statefulset-0       1/1     Running   14         5d10h
kafka-statefulset-1       1/1     Running   14         5d10h
kafka-statefulset-2       1/1     Running   16         5d10h
kafka-statefulset-3       1/1     Running   14         5d10h
kafka-statefulset-4       1/1     Running   14         5d10h
zookeeper-statefulset-0   1/1     Running   5          5d10h
zookeeper-statefulset-1   1/1     Running   5          5d10h
zookeeper-statefulset-2   1/1     Running   5          5d10h
</code>```

My problem is that I do not really understand how can I check if they can communicate properly.

What I have already tried -
I tried -

```<code> kafkacat -L -b kafka-statefulset-0.kafka headless.default.svc.cluster.local:9093
</code>```

and got -

% ERROR: Failed to acquire metadata: Local: Broker transport failure

I tried -

```<code>kafkacat -b 172.17.0.10:9093 -t second_topic -P
</code>```

and got -

```<code>% ERROR: Local: Host resolution failure: kafka-statefulset-0.kafka-headless.default.svc.cluster.local:9093/0: Failed to resolve 'kafka-statefulset-0.kafka-headless.default.svc.cluster.local:9093': Name or service not known
% ERROR: Local: Host resolution failure: kafka-statefulset-1.kafka-headless.default.svc.cluster.local:9093/1: Failed to resolve 'kafka-statefulset-1.kafka-headless.default.svc.cluster.local:9093': Name or service not known
% ERROR: Local: Host resolution failure: kafka-statefulset-3.kafka-headless.default.svc.cluster.local:9093/3: Failed to resolve 'kafka-statefulset-3.kafka-headless.default.svc.cluster.local:9093': Name or service not known
% ERROR: Local: Host resolution failure: kafka-statefulset-4.kafka-headless.default.svc.cluster.local:9093/4: Failed to resolve 'kafka-statefulset-4.kafka-headless.default.svc.cluster.local:9093': Name or service not known
% ERROR: Local: Host resolution failure: kafka-statefulset-2.kafka-headless.default.svc.cluster.local:9093/2: Failed to resolve 'kafka-statefulset-2.kafka-headless.default.svc.cluster.local:9093': Name or service not known
</code>```

but when I ran -

```<code>kafkacat -L -b 172.17.0.10:9093
</code>```

I get -

```<code>Metadata for all topics (from broker -1: 172.17.0.10:9093/bootstrap):
 5 brokers:
  broker 2 at kafka-statefulset-2.kafka-headless.default.svc.cluster.local:9093
  broker 4 at kafka-statefulset-4.kafka-headless.default.svc.cluster.local:9093
  broker 1 at kafka-statefulset-1.kafka-headless.default.svc.cluster.local:9093
  broker 3 at kafka-statefulset-3.kafka-headless.default.svc.cluster.local:9093
  broker 0 at kafka-statefulset-0.kafka-headless.default.svc.cluster.local:9093
 4 topics:
  topic "second_topic" with 1 partitions:
    partition 0, leader 4, replicas: 4, isrs: 4
</code>```

As I understand right now, I have not configured the services correctly for connecting with them from outside the cluster, but I can connect to them from within the cluster.
Although I can communicate with them from within the cluster, I keep getting errors I can't understand.

For example (installing Kafkacat inside the pod's container and trying to talk with other Kafka's broker) -

```<code> > kubectl exec -it  kafka-statefulset-0 bash
 > apt-get install kafkacat
 > kafkacat -b kafka-statefulset-1.kafka-headless.default.svc.cluster.local:9093 -t TOPIC -P
 > kafkacat -L -b kafka-statefulset-1.kafka-headless.default.svc.cluster.local:9093
</code>```

I got the right metadata but with error in the end -

```<code>etadata for all topics (from broker -1: kafka-statefulset-1.kafka-headless.default.svc.cluster.local:9093/bootstrap):
 5 brokers:
  broker 2 at kafka-statefulset-2.kafka-headless.default.svc.cluster.local:9093
  broker 4 at kafka-statefulset-4.kafka-headless.default.svc.cluster.local:9093
  broker 1 at kafka-statefulset-1.kafka-headless.default.svc.cluster.local:9093
  broker 3 at kafka-statefulset-3.kafka-headless.default.svc.cluster.local:9093
  broker 0 at kafka-statefulset-0.kafka-headless.default.svc.cluster.local:9093
 5 topics:
  topic "TOPIC" with 1 partitions:
    partition 0, leader 2, replicas: 2, isrs: 2
  topic "second_topic" with 1 partitions:
    partition 0, leader 4, replicas: 4, isrs: 4
  topic "first_topic" with 1 partitions:
    partition 0, leader 2, replicas: 2, isrs: 2
  topic "nir_topic" with 1 partitions:
    partition 0, leader 0, replicas: 0, isrs: 0
  topic "first" with 1 partitions:
    partition 0, leader 3, replicas: 3, isrs: 3
%3|1581685918.022|FAIL|rdkafka#producer-0| kafka-statefulset-0.kafka-headless.default.svc.cluster.local:9093/0: Failed to connect to broker at kafka-statefulset-0.kafka-headless.default.svc.cluster.local:: Interrupted system call
%3|1581685918.022|ERROR|rdkafka#producer-0| kafka-statefulset-0.kafka-headless.default.svc.cluster.local:9093/0: Failed to connect to broker at kafka-statefulset-0.kafka-headless.default.svc.cluster.local:: Interrupted system call
%3|1581685918.022|FAIL|rdkafka#producer-0| kafka-statefulset-2.kafka-headless.default.svc.cluster.local:9093/2: Failed to connect to broker at kafka-statefulset-2.kafka-headless.default.svc.cluster.local:: Interrupted system call
%3|1581685918.022|ERROR|rdkafka#producer-0| kafka-statefulset-2.kafka-headless.default.svc.cluster.local:9093/2: Failed to connect to broker at kafka-statefulset-2.kafka-headless.default.svc.cluster.local:: Interrupted system call
%3|1581685918.023|FAIL|rdkafka#producer-0| kafka-statefulset-4.kafka-headless.default.svc.cluster.local:9093/4: Failed to connect to broker at kafka-statefulset-4.kafka-headless.default.svc.cluster.local:: Interrupted system call
%3|1581685918.023|ERROR|rdkafka#producer-0| kafka-statefulset-4.kafka-headless.default.svc.cluster.local:9093/4: Failed to connect to broker at kafka-statefulset-4.kafka-headless.default.svc.cluster.local:: Interrupted system call
</code>```

What cloud be the problem?
How can I check the communication between them and check the functionalities correctness of both of them - Kafka and Zookeeper?

Some more information about the system (I can copy all the YAML configuration if needed, but it is pretty long)-

There is a Statefulset of Kafka and Statefulset of Zookeeper.

Kafka's Broker can talk with the zookeeper through port 2181.
My configuration is -

-override zookeeper.connect=zookeeper-statefulset-0.zookeeper-headless.default.svc.cluster.local:2181 ...

I also built headless service for talking with each Kafka's Broker through port 9093

Zookeeper ports:

a. 2181 - client port

b. 2888 - server port

c. 3888 - port for leader election

5.The services which run -

```<code>NAME                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)             AGE
kafka-headless       ClusterIP   None            <none>        9093/TCP            5d10h
kubernetes           ClusterIP   10.96.0.1       <none>        443/TCP             5d11h
zookeeper-cs         ClusterIP   10.106.99.170   <none>        2181/TCP            5d11h
zookeeper-headless   ClusterIP   None            <none>        2888/TCP,3888/TCP   5d11h
</code>```

UPDATE - Adding Kafka and Zookeeper configuration files
kafka -

```<code>apiVersion: apps/v1
kind: StatefulSet
metadata:
spec:
  selector:
    matchLabels:
      app: kafka-app
  serviceName: kafka-headless
  replicas: 5
  podManagementPolicy: Parallel
  template:
    metadata:
      labels:
        app: kafka-app
        kafkaMinReplicas: need-supervision
    spec:
      affinity:
        podAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
             - weight: 1
               podAffinityTerm:
                 labelSelector:
                    matchExpressions:
                      - key: "app"
                        operator: In
                        values:
                        - zookeeper-app
                 topologyKey: "kubernetes.io/hostname"
      terminationGracePeriodSeconds: 300
      containers:
      - name: k8skafka
        imagePullPolicy: Always
        image: gcr.io/google_containers/kubernetes-kafka:1.0-10.2.1
        resources:
          requests:
            memory: "1Gi"
            cpu: 500m
        ports:
        - containerPort: 9093
          name: server
        command:
        - sh
        - -c
        - "exec kafka-server-start.sh /opt/kafka/config/server.properties --override broker.id=${HOSTNAME##*-} \
          --override listeners=PLAINTEXT://:9093 \
          --override zookeeper.connect=zookeeper-statefulset-0.zookeeper-headless.default.svc.cluster.local:2181,zookeeper-statefulset-1.zookeeper-headless.default.svc.cluster.local:2181,zookeeper-statefulset-2.zookeeper-headless.default.svc.cluster.local:2181 \
          --override log.dir=/var/lib/kafka \
          --override auto.create.topics.enable=true \
          --override auto.leader.rebalance.enable=true \
          --override background.threads=10 \
          --override compression.type=producer \
          --override delete.topic.enable=false \
          --override leader.imbalance.check.interval.seconds=300 \
          --override leader.imbalance.per.broker.percentage=10 \
          --override log.flush.interval.messages=9223372036854775807 \
          --override log.flush.offset.checkpoint.interval.ms=60000 \
          --override log.flush.scheduler.interval.ms=9223372036854775807 \
          --override log.retention.bytes=-1 \
          --override log.retention.hours=168 \
          --override log.roll.hours=168 \
          --override log.roll.jitter.hours=0 \
          --override log.segment.bytes=1073741824 \
          --override log.segment.delete.delay.ms=60000 \
          --override message.max.bytes=1000012 \
          --override min.insync.replicas=1 \
          --override num.io.threads=8 \
          --override num.network.threads=3 \
          --override num.recovery.threads.per.data.dir=1 \
          --override num.replica.fetchers=1 \
          --override offset.metadata.max.bytes=4096 \
          --override offsets.commit.required.acks=-1 \
          --override offsets.commit.timeout.ms=5000 \
          --override offsets.load.buffer.size=5242880 \
          --override offsets.retention.check.interval.ms=600000 \
          --override offsets.retention.minutes=1440 \
          --override offsets.topic.compression.codec=0 \
          --override offsets.topic.num.partitions=50 \
          --override offsets.topic.replication.factor=3 \
          --override offsets.topic.segment.bytes=104857600 \
          --override queued.max.requests=500 \
          --override quota.consumer.default=9223372036854775807 \
          --override quota.producer.default=9223372036854775807 \
          --override replica.fetch.min.bytes=1 \
          --override replica.fetch.wait.max.ms=500 \
          --override replica.high.watermark.checkpoint.interval.ms=5000 \
          --override replica.lag.time.max.ms=10000 \
          --override replica.socket.receive.buffer.bytes=65536 \
          --override replica.socket.timeout.ms=30000 \
          --override request.timeout.ms=30000 \
          --override socket.receive.buffer.bytes=102400 \
          --override socket.request.max.bytes=104857600 \
          --override socket.send.buffer.bytes=102400 \
          --override unclean.leader.election.enable=true \
          --override zookeeper.session.timeout.ms=30000 \
          --override zookeeper.set.acl=false \
          --override broker.id.generation.enable=true \
          --override connections.max.idle.ms=600000 \
          --override controlled.shutdown.enable=true \
          --override controlled.shutdown.max.retries=3 \
          --override controlled.shutdown.retry.backoff.ms=5000 \
          --override controller.socket.timeout.ms=30000 \
          --override default.replication.factor=1 \
          --override fetch.purgatory.purge.interval.requests=1000 \
          --override group.max.session.timeout.ms=300000 \
          --override group.min.session.timeout.ms=6000 \
          --override inter.broker.protocol.version=0.10.2-IV0 \
          --override log.cleaner.backoff.ms=15000 \
          --override log.cleaner.dedupe.buffer.size=134217728 \
          --override log.cleaner.delete.retention.ms=86400000 \
          --override log.cleaner.enable=true \
          --override log.cleaner.io.buffer.load.factor=0.9 \
          --override log.cleaner.io.buffer.size=524288 \
          --override log.cleaner.io.max.bytes.per.second=1.7976931348623157E308 \
          --override log.cleaner.min.cleanable.ratio=0.5 \
          --override log.cleaner.min.compaction.lag.ms=0 \
          --override log.cleaner.threads=1 \
          --override log.cleanup.policy=delete \
          --override log.index.interval.bytes=4096 \
          --override log.index.size.max.bytes=10485760 \
          --override log.message.timestamp.difference.max.ms=9223372036854775807 \
          --override log.message.timestamp.type=CreateTime \
          --override log.preallocate=false \
          --override log.retention.check.interval.ms=300000 \
          --override max.connections.per.ip=2147483647 \
          --override num.partitions=1 \
          --override producer.purgatory.purge.interval.requests=1000 \
          --override replica.fetch.backoff.ms=1000 \
          --override replica.fetch.max.bytes=1048576 \
          --override replica.fetch.response.max.bytes=10485760 \
          --override reserved.broker.max.id=1000 "
        env:
        - name: KAFKA_HEAP_OPTS
          value : "-Xmx512M -Xms512M"
        - name: KAFKA_OPTS
          value: "-Dlogging.level=INFO"
        volumeMounts:
        - name: datadir
          mountPath: /var/lib/kafka
        readinessProbe:
          exec:
            command:
            - sh
            - -c
            - "/opt/kafka/bin/kafka-broker-api-versions.sh --bootstrap-server=localhost:9093"
      securityContext:
        fsGroup: 1000
  volumeClaimTemplates:
  - metadata:
      name: datadir
    spec:
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: 1Gi
</code>```

Zookeeper -

```<code>apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: zookeeper-statefulset
spec:
  selector:
    matchLabels:
      app: zookeeper-app
  serviceName: zookeeper-headless
  replicas: 5
  updateStrategy:
    type: RollingUpdate
  podManagementPolicy: OrderedReady
  template:
    metadata:
      labels:
        app: zookeeper-app
    spec:
      containers:
      - name: kubernetes-zookeeper
        imagePullPolicy: Always
        image: "k8s.gcr.io/kubernetes-zookeeper:1.0-3.4.10"
        resources:
          requests:
            memory: "1Gi"
            cpu: "0.5"

        ports:
        # Expose by zookeeper-cs to the client
        - containerPort: 2181
          name: client
        # Expose by zookeeper-headless to the other replicas of the set
        - containerPort: 2888
          name: server
        - containerPort: 3888
          name: leader-election
        command:
        - sh
        - -c
        - "start-zookeeper \
          --servers=3 \
          --data_dir=/var/lib/zookeeper/data \
          --data_log_dir=/var/lib/zookeeper/data/log \
          --conf_dir=/opt/zookeeper/conf \
          --client_port=2181 \
          --election_port=3888 \
          --server_port=2888 \
          --tick_time=2000 \
          --init_limit=10 \
          --sync_limit=5 \
          --heap=512M \
          --max_client_cnxns=60 \
          --snap_retain_count=3 \
          --purge_interval=12 \
          --max_session_timeout=40000 \
          --min_session_timeout=4000 \
          --log_level=INFO"
        readinessProbe:
          exec:
            command: ["sh", "-c", "zookeeper-ready 2181"]
          initialDelaySeconds: 60
          timeoutSeconds: 10
        livenessProbe:
          exec:
            command:
            - sh
            - -c
            - "zookeeper-ready 2181"
          initialDelaySeconds: 60
          timeoutSeconds: 10
        volumeMounts:
        - name: zookeeper-volume
          mountPath: /var/lib/zookeeper
      securityContext:
        fsGroup: 1000
  volumeClaimTemplates:
  - metadata:
      name: zookeeper-volume
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 1Gi
</code>```

答:
kafkacat -L -b kafka-statefulset-0.kafka headless.default.svc.cluster.local:9093

Doesn't work. There is a space in there after the first -b flag

kafkacat -b 172.17.0.10:9093 -t second_topic -P

Without the correct advertised.listeners that return the resolvable addresses of brokers, this won't work.

kafkacat -L -b 172.17.0.10:9093

This is a step in the right direction, but you're using the Docker network IP, and not a Cluster / Node Port of any of the services, still isn't portable to other machines outside your cluster.

installing Kafkacat inside the pod's container and trying to talk with other Kafka's broker

That's a good test to make sure that replication will at least work, but doesn't solve the external client issue.

I got the right metadata but with error in the end

That could be a sign that your healthcheck on the broker or zookeeper is failing and the pod is restarting. Notice that the error cycles from 0,2,4...

I also built headless service for talking with each Kafka's Broker through port 9093

Okay, great, but you need to set advertised.listeners of each broker to now accept connections on 9093.

All in all, I think just using existing Kafka Helm charts that allow for external connectivity would be your best option.

Body:
As part of my system, I need to use Kafka and Zookeeper cluster on top of Kubernetes.
I'm using Statefulset for deploying them and use headless service for Kafka's Broker to be able to talk with the Zookeeper servers.

Its seems that the clusters are running - (by typing kubectl get pods)

NAME                      READY   STATUS    RESTARTS   AGE
kafka-statefulset-0       1/1     Running   14         5d10h
kafka-statefulset-1       1/1     Running   14         5d10h
kafka-statefulset-2       1/1     Running   16         5d10h
kafka-statefulset-3       1/1     Running   14         5d10h
kafka-statefulset-4       1/1     Running   14         5d10h
zookeeper-statefulset-0   1/1     Running   5          5d10h
zookeeper-statefulset-1   1/1     Running   5          5d10h
zookeeper-statefulset-2   1/1     Running   5          5d10h

My problem is that I do not really understand how can I check if they can communicate properly.

What I have already tried -
I tried -

 kafkacat -L -b kafka-statefulset-0.kafka headless.default.svc.cluster.local:9093

and got -

% ERROR: Failed to acquire metadata: Local: Broker transport failure

I tried -

kafkacat -b 172.17.0.10:9093 -t second_topic -P

and got -

% ERROR: Local: Host resolution failure: kafka-statefulset-0.kafka-headless.default.svc.cluster.local:9093/0: Failed to resolve 'kafka-statefulset-0.kafka-headless.default.svc.cluster.local:9093': Name or service not known
% ERROR: Local: Host resolution failure: kafka-statefulset-1.kafka-headless.default.svc.cluster.local:9093/1: Failed to resolve 'kafka-statefulset-1.kafka-headless.default.svc.cluster.local:9093': Name or service not known
% ERROR: Local: Host resolution failure: kafka-statefulset-3.kafka-headless.default.svc.cluster.local:9093/3: Failed to resolve 'kafka-statefulset-3.kafka-headless.default.svc.cluster.local:9093': Name or service not known
% ERROR: Local: Host resolution failure: kafka-statefulset-4.kafka-headless.default.svc.cluster.local:9093/4: Failed to resolve 'kafka-statefulset-4.kafka-headless.default.svc.cluster.local:9093': Name or service not known
% ERROR: Local: Host resolution failure: kafka-statefulset-2.kafka-headless.default.svc.cluster.local:9093/2: Failed to resolve 'kafka-statefulset-2.kafka-headless.default.svc.cluster.local:9093': Name or service not known

but when I ran -

kafkacat -L -b 172.17.0.10:9093

I get -

Metadata for all topics (from broker -1: 172.17.0.10:9093/bootstrap):
 5 brokers:
  broker 2 at kafka-statefulset-2.kafka-headless.default.svc.cluster.local:9093
  broker 4 at kafka-statefulset-4.kafka-headless.default.svc.cluster.local:9093
  broker 1 at kafka-statefulset-1.kafka-headless.default.svc.cluster.local:9093
  broker 3 at kafka-statefulset-3.kafka-headless.default.svc.cluster.local:9093
  broker 0 at kafka-statefulset-0.kafka-headless.default.svc.cluster.local:9093
 4 topics:
  topic "second_topic" with 1 partitions:
    partition 0, leader 4, replicas: 4, isrs: 4

As I understand right now, I have not configured the services correctly for connecting with them from outside the cluster, but I can connect to them from within the cluster.
Although I can communicate with them from within the cluster, I keep getting errors I can't understand.

For example (installing Kafkacat inside the pod's container and trying to talk with other Kafka's broker) -

 > kubectl exec -it  kafka-statefulset-0 bash
 > apt-get install kafkacat
 > kafkacat -b kafka-statefulset-1.kafka-headless.default.svc.cluster.local:9093 -t TOPIC -P
 > kafkacat -L -b kafka-statefulset-1.kafka-headless.default.svc.cluster.local:9093

I got the right metadata but with error in the end -

etadata for all topics (from broker -1: kafka-statefulset-1.kafka-headless.default.svc.cluster.local:9093/bootstrap):
 5 brokers:
  broker 2 at kafka-statefulset-2.kafka-headless.default.svc.cluster.local:9093
  broker 4 at kafka-statefulset-4.kafka-headless.default.svc.cluster.local:9093
  broker 1 at kafka-statefulset-1.kafka-headless.default.svc.cluster.local:9093
  broker 3 at kafka-statefulset-3.kafka-headless.default.svc.cluster.local:9093
  broker 0 at kafka-statefulset-0.kafka-headless.default.svc.cluster.local:9093
 5 topics:
  topic "TOPIC" with 1 partitions:
    partition 0, leader 2, replicas: 2, isrs: 2
  topic "second_topic" with 1 partitions:
    partition 0, leader 4, replicas: 4, isrs: 4
  topic "first_topic" with 1 partitions:
    partition 0, leader 2, replicas: 2, isrs: 2
  topic "nir_topic" with 1 partitions:
    partition 0, leader 0, replicas: 0, isrs: 0
  topic "first" with 1 partitions:
    partition 0, leader 3, replicas: 3, isrs: 3
%3|1581685918.022|FAIL|rdkafka#producer-0| kafka-statefulset-0.kafka-headless.default.svc.cluster.local:9093/0: Failed to connect to broker at kafka-statefulset-0.kafka-headless.default.svc.cluster.local:: Interrupted system call
%3|1581685918.022|ERROR|rdkafka#producer-0| kafka-statefulset-0.kafka-headless.default.svc.cluster.local:9093/0: Failed to connect to broker at kafka-statefulset-0.kafka-headless.default.svc.cluster.local:: Interrupted system call
%3|1581685918.022|FAIL|rdkafka#producer-0| kafka-statefulset-2.kafka-headless.default.svc.cluster.local:9093/2: Failed to connect to broker at kafka-statefulset-2.kafka-headless.default.svc.cluster.local:: Interrupted system call
%3|1581685918.022|ERROR|rdkafka#producer-0| kafka-statefulset-2.kafka-headless.default.svc.cluster.local:9093/2: Failed to connect to broker at kafka-statefulset-2.kafka-headless.default.svc.cluster.local:: Interrupted system call
%3|1581685918.023|FAIL|rdkafka#producer-0| kafka-statefulset-4.kafka-headless.default.svc.cluster.local:9093/4: Failed to connect to broker at kafka-statefulset-4.kafka-headless.default.svc.cluster.local:: Interrupted system call
%3|1581685918.023|ERROR|rdkafka#producer-0| kafka-statefulset-4.kafka-headless.default.svc.cluster.local:9093/4: Failed to connect to broker at kafka-statefulset-4.kafka-headless.default.svc.cluster.local:: Interrupted system call

What cloud be the problem?
How can I check the communication between them and check the functionalities correctness of both of them - Kafka and Zookeeper?

Some more information about the system (I can copy all the YAML configuration if needed, but it is pretty long)-

There is a Statefulset of Kafka and Statefulset of Zookeeper.

Kafka's Broker can talk with the zookeeper through port 2181.
My configuration is -

-override zookeeper.connect=zookeeper-statefulset-0.zookeeper-headless.default.svc.cluster.local:2181 ...

I also built headless service for talking with each Kafka's Broker through port 9093

Zookeeper ports:

a. 2181 - client port

b. 2888 - server port

c. 3888 - port for leader election

5.The services which run -

NAME                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)             AGE
kafka-headless       ClusterIP   None            <none>        9093/TCP            5d10h
kubernetes           ClusterIP   10.96.0.1       <none>        443/TCP             5d11h
zookeeper-cs         ClusterIP   10.106.99.170   <none>        2181/TCP            5d11h
zookeeper-headless   ClusterIP   None            <none>        2888/TCP,3888/TCP   5d11h

UPDATE - Adding Kafka and Zookeeper configuration files
kafka -

apiVersion: apps/v1
kind: StatefulSet
metadata:
spec:
  selector:
    matchLabels:
      app: kafka-app
  serviceName: kafka-headless
  replicas: 5
  podManagementPolicy: Parallel
  template:
    metadata:
      labels:
        app: kafka-app
        kafkaMinReplicas: need-supervision
    spec:
      affinity:
        podAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
             - weight: 1
               podAffinityTerm:
                 labelSelector:
                    matchExpressions:
                      - key: "app"
                        operator: In
                        values:
                        - zookeeper-app
                 topologyKey: "kubernetes.io/hostname"
      terminationGracePeriodSeconds: 300
      containers:
      - name: k8skafka
        imagePullPolicy: Always
        image: gcr.io/google_containers/kubernetes-kafka:1.0-10.2.1
        resources:
          requests:
            memory: "1Gi"
            cpu: 500m
        ports:
        - containerPort: 9093
          name: server
        command:
        - sh
        - -c
        - "exec kafka-server-start.sh /opt/kafka/config/server.properties --override broker.id=${HOSTNAME##*-} \
          --override listeners=PLAINTEXT://:9093 \
          --override zookeeper.connect=zookeeper-statefulset-0.zookeeper-headless.default.svc.cluster.local:2181,zookeeper-statefulset-1.zookeeper-headless.default.svc.cluster.local:2181,zookeeper-statefulset-2.zookeeper-headless.default.svc.cluster.local:2181 \
          --override log.dir=/var/lib/kafka \
          --override auto.create.topics.enable=true \
          --override auto.leader.rebalance.enable=true \
          --override background.threads=10 \
          --override compression.type=producer \
          --override delete.topic.enable=false \
          --override leader.imbalance.check.interval.seconds=300 \
          --override leader.imbalance.per.broker.percentage=10 \
          --override log.flush.interval.messages=9223372036854775807 \
          --override log.flush.offset.checkpoint.interval.ms=60000 \
          --override log.flush.scheduler.interval.ms=9223372036854775807 \
          --override log.retention.bytes=-1 \
          --override log.retention.hours=168 \
          --override log.roll.hours=168 \
          --override log.roll.jitter.hours=0 \
          --override log.segment.bytes=1073741824 \
          --override log.segment.delete.delay.ms=60000 \
          --override message.max.bytes=1000012 \
          --override min.insync.replicas=1 \
          --override num.io.threads=8 \
          --override num.network.threads=3 \
          --override num.recovery.threads.per.data.dir=1 \
          --override num.replica.fetchers=1 \
          --override offset.metadata.max.bytes=4096 \
          --override offsets.commit.required.acks=-1 \
          --override offsets.commit.timeout.ms=5000 \
          --override offsets.load.buffer.size=5242880 \
          --override offsets.retention.check.interval.ms=600000 \
          --override offsets.retention.minutes=1440 \
          --override offsets.topic.compression.codec=0 \
          --override offsets.topic.num.partitions=50 \
          --override offsets.topic.replication.factor=3 \
          --override offsets.topic.segment.bytes=104857600 \
          --override queued.max.requests=500 \
          --override quota.consumer.default=9223372036854775807 \
          --override quota.producer.default=9223372036854775807 \
          --override replica.fetch.min.bytes=1 \
          --override replica.fetch.wait.max.ms=500 \
          --override replica.high.watermark.checkpoint.interval.ms=5000 \
          --override replica.lag.time.max.ms=10000 \
          --override replica.socket.receive.buffer.bytes=65536 \
          --override replica.socket.timeout.ms=30000 \
          --override request.timeout.ms=30000 \
          --override socket.receive.buffer.bytes=102400 \
          --override socket.request.max.bytes=104857600 \
          --override socket.send.buffer.bytes=102400 \
          --override unclean.leader.election.enable=true \
          --override zookeeper.session.timeout.ms=30000 \
          --override zookeeper.set.acl=false \
          --override broker.id.generation.enable=true \
          --override connections.max.idle.ms=600000 \
          --override controlled.shutdown.enable=true \
          --override controlled.shutdown.max.retries=3 \
          --override controlled.shutdown.retry.backoff.ms=5000 \
          --override controller.socket.timeout.ms=30000 \
          --override default.replication.factor=1 \
          --override fetch.purgatory.purge.interval.requests=1000 \
          --override group.max.session.timeout.ms=300000 \
          --override group.min.session.timeout.ms=6000 \
          --override inter.broker.protocol.version=0.10.2-IV0 \
          --override log.cleaner.backoff.ms=15000 \
          --override log.cleaner.dedupe.buffer.size=134217728 \
          --override log.cleaner.delete.retention.ms=86400000 \
          --override log.cleaner.enable=true \
          --override log.cleaner.io.buffer.load.factor=0.9 \
          --override log.cleaner.io.buffer.size=524288 \
          --override log.cleaner.io.max.bytes.per.second=1.7976931348623157E308 \
          --override log.cleaner.min.cleanable.ratio=0.5 \
          --override log.cleaner.min.compaction.lag.ms=0 \
          --override log.cleaner.threads=1 \
          --override log.cleanup.policy=delete \
          --override log.index.interval.bytes=4096 \
          --override log.index.size.max.bytes=10485760 \
          --override log.message.timestamp.difference.max.ms=9223372036854775807 \
          --override log.message.timestamp.type=CreateTime \
          --override log.preallocate=false \
          --override log.retention.check.interval.ms=300000 \
          --override max.connections.per.ip=2147483647 \
          --override num.partitions=1 \
          --override producer.purgatory.purge.interval.requests=1000 \
          --override replica.fetch.backoff.ms=1000 \
          --override replica.fetch.max.bytes=1048576 \
          --override replica.fetch.response.max.bytes=10485760 \
          --override reserved.broker.max.id=1000 "
        env:
        - name: KAFKA_HEAP_OPTS
          value : "-Xmx512M -Xms512M"
        - name: KAFKA_OPTS
          value: "-Dlogging.level=INFO"
        volumeMounts:
        - name: datadir
          mountPath: /var/lib/kafka
        readinessProbe:
          exec:
            command:
            - sh
            - -c
            - "/opt/kafka/bin/kafka-broker-api-versions.sh --bootstrap-server=localhost:9093"
      securityContext:
        fsGroup: 1000
  volumeClaimTemplates:
  - metadata:
      name: datadir
    spec:
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: 1Gi

Zookeeper -

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: zookeeper-statefulset
spec:
  selector:
    matchLabels:
      app: zookeeper-app
  serviceName: zookeeper-headless
  replicas: 5
  updateStrategy:
    type: RollingUpdate
  podManagementPolicy: OrderedReady
  template:
    metadata:
      labels:
        app: zookeeper-app
    spec:
      containers:
      - name: kubernetes-zookeeper
        imagePullPolicy: Always
        image: "k8s.gcr.io/kubernetes-zookeeper:1.0-3.4.10"
        resources:
          requests:
            memory: "1Gi"
            cpu: "0.5"

        ports:
        # Expose by zookeeper-cs to the client
        - containerPort: 2181
          name: client
        # Expose by zookeeper-headless to the other replicas of the set
        - containerPort: 2888
          name: server
        - containerPort: 3888
          name: leader-election
        command:
        - sh
        - -c
        - "start-zookeeper \
          --servers=3 \
          --data_dir=/var/lib/zookeeper/data \
          --data_log_dir=/var/lib/zookeeper/data/log \
          --conf_dir=/opt/zookeeper/conf \
          --client_port=2181 \
          --election_port=3888 \
          --server_port=2888 \
          --tick_time=2000 \
          --init_limit=10 \
          --sync_limit=5 \
          --heap=512M \
          --max_client_cnxns=60 \
          --snap_retain_count=3 \
          --purge_interval=12 \
          --max_session_timeout=40000 \
          --min_session_timeout=4000 \
          --log_level=INFO"
        readinessProbe:
          exec:
            command: ["sh", "-c", "zookeeper-ready 2181"]
          initialDelaySeconds: 60
          timeoutSeconds: 10
        livenessProbe:
          exec:
            command:
            - sh
            - -c
            - "zookeeper-ready 2181"
          initialDelaySeconds: 60
          timeoutSeconds: 10
        volumeMounts:
        - name: zookeeper-volume
          mountPath: /var/lib/zookeeper
      securityContext:
        fsGroup: 1000
  volumeClaimTemplates:
  - metadata:
      name: zookeeper-volume
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 1Gi


问:
How can I eliminate vertical space between rows of buttons in an HTML table?
I have a div that pops up when the "PATTERNS" button is pressed. This div holds a table of buttons (see pic). I want all of the buttons to be touching however I can't seem to get rid of the row spaces in between them. I am not an experienced html table user.

My research has led me to try the following, is my table layout optimal here?:

.ButtonTable {
  display: block;
  background: rgb(116, 116, 116);
  position: absolute;
  margin: 0;
  padding: 0;
  left: 2%;
  width: 80%;
  height: 70%;
  /*BOX HEIGHT*/
  z-index: 1002;
  overflow: auto;
  opacity: .80;
  filter: alpha(opacity=80);
  border-spacing: 0;
  border-collapse: collapse;
}

.PatternButton {
  border-radius: 4px;
  width: 200px;
  transition-duration: 0.2s;
  color: black;
  background-color: white;
  font-size: 10px;
  font-weight: bold;
  padding: 0;
  margin: 0;
  display: inline-block;
  border: none;
}```
<pre class="snippet-code-html lang-html prettyprint-override"><code><table className="ButtonTable" cellspacing="0">
  <td className="Col12">
    <th className="Title1">col1</th>
    <button className="PatternButton">1</button><br></br>
    <button className="PatternButton">2</button><br></br>
    <button className="PatternButton">3</button><br></br>
    <button className="PatternButton">4</button><br></br>
    <button className="PatternButton">5</button><br></br>
    <button className="PatternButton">6</button><br></br>
    <th className="Title2">col2</th>
    <button className="PatternButton">1</button><br></br>
    <button className="PatternButton">2</button><br></br>
    <button className="PatternButton">3</button><br></br>
    <button className="PatternButton">4</button><br></br>
    <button className="PatternButton">5</button><br></br>
    <button className="PatternButton">6</button><br></br>
  </td>
  <td className="Col34">
    <th className="Title3">col3</th>
    <button className="PatternButton">1</button><br></br>
    <button className="PatternButton">2</button><br></br>
    <button className="PatternButton">3</button><br></br>
    <button className="PatternButton">4</button><br></br>
    <button className="PatternButton">5</button><br></br>
    <button className="PatternButton">6</button><br></br>
    <th className="Title4">col4</th>
    <button className="PatternButton">1</button><br></br>
    <button className="PatternButton">2</button><br></br>
    <button className="PatternButton">3</button><br></br>
    <button className="PatternButton">4</button><br></br>
    <button className="PatternButton">5</button><br></br>
    <button className="PatternButton">6</button><br></br>
  </td>
  <td className="Col5">
    <th className="Title5">col5</th>
    <button className="PatternButton">1</button><br></br>
    <button className="PatternButton">2</button><br></br>
    <button className="PatternButton">3</button><br></br>
    <button className="PatternButton">4</button><br></br>
    <button className="PatternButton">5</button><br></br>
    <button className="PatternButton">6</button><br></br>
    <button className="PatternButton">7</button><br></br>
    <button className="PatternButton">8</button><br></br>
  </td>
  <td className="Col6">
    <th className="Title6">col6</th>
    <button className="PatternButton">1</button><br></br>
    <button className="PatternButton">2</button><br></br>
    <button className="PatternButton">3</button><br></br>
    <button className="PatternButton">4</button><br></br>
    <button className="PatternButton">5</button><br></br>
    <button className="PatternButton">6</button><br></br>
    <button className="PatternButton">7</button><br></br>
    <button className="PatternButton">8</button><br></br>
  </td>
</table></code>```

答:
First: YOU NEED TO UNDERSTAND WHAT YOUR DID WRONG

Mistake:
You used
 to break line after every button, thus creating that extra space.
Here: <button className="PatternButton">1</button>

Solution:
Remove the line break
 and set  display: block for your buttons and they'll line up as a column.

.ButtonTable {
    display: block;
    background: rgb(116, 116, 116);
    position: absolute;
    margin: 0;
    padding: 0;
    left: 2%;
    width: 80%;
    height: 70%; /*BOX HEIGHT*/
    z-index: 1002;
    overflow: auto;
    opacity: .80;
    filter: alpha(opacity=80);
    border-spacing:0;
    border-collapse: collapse;
}
.PatternButton {
    border-radius: 4px;
    width: 200px;
    transition-duration: 0.2s;
    color: black;
    background-color: white;
    font-size: 10px;
    font-weight: bold;
    /* just for illustration I've added the following */
    padding: 15px;
    display: block;
    border: thin solid grey;
}```
<pre class="snippet-code-html lang-html prettyprint-override"><code><!-- Just recreated the HTML so tat I can format it on html, and not jsx -->
<table class="ButtonTable" cellspacing="0">
  <td class="Col12">
    <button class="PatternButton">1</button>
    <button class="PatternButton">1</button>
    <button class="PatternButton">1</button>
    <button class="PatternButton">1</button>
    <button class="PatternButton">1</button>
    <button class="PatternButton">1</button>
    <button class="PatternButton">1</button>
    <button class="PatternButton">1</button>
  </td>
</table></code>```

Body:
I have a div that pops up when the "PATTERNS" button is pressed. This div holds a table of buttons (see pic). I want all of the buttons to be touching however I can't seem to get rid of the row spaces in between them. I am not an experienced html table user.

My research has led me to try the following, is my table layout optimal here?:

.ButtonTable {
  display: block;
  background: rgb(116, 116, 116);
  position: absolute;
  margin: 0;
  padding: 0;
  left: 2%;
  width: 80%;
  height: 70%;
  /*BOX HEIGHT*/
  z-index: 1002;
  overflow: auto;
  opacity: .80;
  filter: alpha(opacity=80);
  border-spacing: 0;
  border-collapse: collapse;
}

.PatternButton {
  border-radius: 4px;
  width: 200px;
  transition-duration: 0.2s;
  color: black;
  background-color: white;
  font-size: 10px;
  font-weight: bold;
  padding: 0;
  margin: 0;
  display: inline-block;
  border: none;
}

    col1
    <button className="PatternButton">1</button>

    <button className="PatternButton">2</button>

    <button className="PatternButton">3</button>

    <button className="PatternButton">4</button>

    <button className="PatternButton">5</button>

    <button className="PatternButton">6</button>

    col2
    <button className="PatternButton">1</button>

    <button className="PatternButton">2</button>

    <button className="PatternButton">3</button>

    <button className="PatternButton">4</button>

    <button className="PatternButton">5</button>

    <button className="PatternButton">6</button>

    col3
    <button className="PatternButton">1</button>

    <button className="PatternButton">2</button>

    <button className="PatternButton">3</button>

    <button className="PatternButton">4</button>

    <button className="PatternButton">5</button>

    <button className="PatternButton">6</button>

    col4
    <button className="PatternButton">1</button>

    <button className="PatternButton">2</button>

    <button className="PatternButton">3</button>

    <button className="PatternButton">4</button>

    <button className="PatternButton">5</button>

    <button className="PatternButton">6</button>

    col5
    <button className="PatternButton">1</button>

    <button className="PatternButton">2</button>

    <button className="PatternButton">3</button>

    <button className="PatternButton">4</button>

    <button className="PatternButton">5</button>

    <button className="PatternButton">6</button>

    <button className="PatternButton">7</button>

    <button className="PatternButton">8</button>

    col6
    <button className="PatternButton">1</button>

    <button className="PatternButton">2</button>

    <button className="PatternButton">3</button>

    <button className="PatternButton">4</button>

    <button className="PatternButton">5</button>

    <button className="PatternButton">6</button>

    <button className="PatternButton">7</button>

    <button className="PatternButton">8</button>

Body:
First: YOU NEED TO UNDERSTAND WHAT YOUR DID WRONG

Mistake:
You used <br> to break line after every button, thus creating that extra space.
Here: <button className="PatternButton">1</button><br></br>

Solution:
Remove the line break <br> and set  display: block for your buttons and they'll line up as a column.

.ButtonTable {
    display: block;
    background: rgb(116, 116, 116);
    position: absolute;
    margin: 0;
    padding: 0;
    left: 2%;
    width: 80%;
    height: 70%; /*BOX HEIGHT*/
    z-index: 1002;
    overflow: auto;
    opacity: .80;
    filter: alpha(opacity=80);
    border-spacing:0;
    border-collapse: collapse;
}
.PatternButton {
    border-radius: 4px;
    width: 200px;
    transition-duration: 0.2s;
    color: black;
    background-color: white;
    font-size: 10px;
    font-weight: bold;
    /* just for illustration I've added the following */
    padding: 15px;
    display: block;
    border: thin solid grey;
}

<!-- Just recreated the HTML so tat I can format it on html, and not jsx -->
<table class="ButtonTable" cellspacing="0">
  <td class="Col12">
    <button class="PatternButton">1</button>
    <button class="PatternButton">1</button>
    <button class="PatternButton">1</button>
    <button class="PatternButton">1</button>
    <button class="PatternButton">1</button>
    <button class="PatternButton">1</button>
    <button class="PatternButton">1</button>
    <button class="PatternButton">1</button>
  </td>
</table>


问:
Java: compile-time resolution and "most specific method" as it applies to variable arity
Could someone help me understand section 15.12.2.5 of the JLS re: most specific method?

(bludgeoned cut&paste from JLS follows)

In addition, one variable arity member method named m is more specific than another variable arity member method of the same name if either:

One member method has n parameters and the other has k parameters, where n >= k. The types of the parameters of the first member method are T1, . . . , Tn-1 , Tn[], the types of the parameters of the other method are U1, . . . , Uk-1, Uk[]. If the second method is generic then let R1 ... Rp p1, be its formal type parameters, let Bl be the declared bound of Rl, 1lp, let A1 ... Ap be the actual type arguments inferred (§15.12.2.7) for this invocation under the initial constraints Ti << Ui,1ik-1, Ti << Uk, kin and let Si = Ui[R1 = A1, ..., Rp = Ap] 1ik; otherwise let Si = Ui, 1ik. Then:
      for all j from 1 to k-1, Tj <: Sj, and,
      for all j from k to n, Tj <: Sk, and,
      If the second method is a generic method as described above then Al <: Bl[R1 = A1, ..., Rp = Ap], 1lp.

One member method has k parameters and the other has n parameters, where n >= k. The types of the parameters of the first method are U1, . . . , Uk-1, Uk[], the types of the parameters of the other method are T1, . . ., Tn-1, Tn[]. If the second method is generic then let R1 ... Rp p1, be its formal type parameters, let Bl be the declared bound of Rl, 1lp, let A1 ... Ap be the actual type arguments inferred (§15.12.2.7) for this invocation under the initial constraints Ui << Ti, 1ik-1, Uk << Ti, kin and let Si = Ti[R1 = A1, ..., Rp = Ap] 1in; otherwise let Si = Ti, 1in. Then:
      for all j from 1 to k-1 , Uj <: Sj, and,
      for all j from k to n , Uk <: Sj, and,
      If the second method is a generic method as described above then Al <: Bl[R1 = A1, ..., Rp = Ap], 1lp.

Ignoring the issue generics, does this mean varargs is more important than subtyping, or subtyping is more important than varargs, when deciding whether one method is more specific than another? I can't figure it out.

Concrete example: Which of the following compute() methods is "more specific" according to the JLS?

```<code>package com.example.test.reflect;

class JLS15Test
{
    int compute(Object o1, Object o2, Object... others) { return 1; }
    int compute(String s1, Object... others)            { return 2; }

    public static void main(String[] args)
    {
        JLS15Test y = new JLS15Test();
        System.out.println(y.compute(y,y,y));
        System.out.println(y.compute("hi",y,y));
    }
}
</code>```

I can't figure out which is "more specific"; the output prints

```<code>1
2
</code>```

I'm confused how to interpret the results. When the first argument was a String, the compiler picked the method with the more specific subtype. When the first argument was an Object, the compiler picked the method with the fewer number of optional varargs.

NOTE: If you are not reading this section of the JLS, and you are giving an answer that depends on the types of the arguments, you are not helping me. If you carefully read the JLS, other than the parts relating to generics, the definition of "more specific" depends on the declared arguments, not on the actual arguments -- this comes into play in other parts of the JLS (can't find it at the moment).

e.g. for fixed arity methods, compute(String s) would be more specific than compute(Object o). But I'm trying to understand the relevant section of the JLS re: variable arity methods.

答:
int compute(String s1, Object... others) is more specific when you call compute("hi",y,y), since String is a subclass of Object.

int compute(Object o1, Object o2, Object... others) is the only match for compute(y,y,y) because the second method receives String as first param, and JLS15Test is not a subclass of String

EDIT

My answer resides on the basics of specific methods, but your code only compiles because of the ability of the compiler to distinguish between the methods in the way described above.

The following examples will not even compile because of its ambiguity:

case 1:

```<code>int compute(Object o1, Object o2, Object... others) { return 1; }
int compute(Object s1, Object... others)            { return 2; }

public static void main(String[] args)
{
    JLS15Test y = new JLS15Test();
    System.out.println(y.compute(y,y,y));
    System.out.println(y.compute("hi",y,y));
}
</code>```

case 2:

```<code>int compute(String o1, Object o2, Object... others) { return 1; }
int compute(Object s1, String... others)            { return 2; }

public static void main(String[] args)
{
    JLS15Test y = new JLS15Test();
    System.out.println(y.compute("hi","hi","hi"));
}
</code>```

More Edit

I didn't get your question well the first two times (and I hope I do this time :) ).

The actual case you are talking about will look like that:

```<code>public class Test {
    public static void main(String[] args)
    {
        Test t = new Test();
        int a = t.compute("t", new Test());
        System.out.println(a);
    }

    int compute(String s, Object... others) { return 1; }
    int compute(Object s1, Object others)   { return 2; }
}
</code>```

In this case, compute(Object s1, Object others) is indeed more specific then compute(String s, Object... others) (has less parameters) so the output will be 2 indeed.

Body:
Could someone help me understand section 15.12.2.5 of the JLS re: most specific method?

(bludgeoned cut&paste from JLS follows)

In addition, one variable arity member method named m is more specific than another variable arity member method of the same name if either:

One member method has n parameters and the other has k parameters, where n >= k. The types of the parameters of the first member method are T1, . . . , Tn-1 , Tn[], the types of the parameters of the other method are U1, . . . , Uk-1, Uk[]. If the second method is generic then let R1 ... Rp p1, be its formal type parameters, let Bl be the declared bound of Rl, 1lp, let A1 ... Ap be the actual type arguments inferred (§15.12.2.7) for this invocation under the initial constraints Ti << Ui,1ik-1, Ti << Uk, kin and let Si = Ui[R1 = A1, ..., Rp = Ap] 1ik; otherwise let Si = Ui, 1ik. Then:
      for all j from 1 to k-1, Tj <: Sj, and,
      for all j from k to n, Tj <: Sk, and,
      If the second method is a generic method as described above then Al <: Bl[R1 = A1, ..., Rp = Ap], 1lp.

One member method has k parameters and the other has n parameters, where n >= k. The types of the parameters of the first method are U1, . . . , Uk-1, Uk[], the types of the parameters of the other method are T1, . . ., Tn-1, Tn[]. If the second method is generic then let R1 ... Rp p1, be its formal type parameters, let Bl be the declared bound of Rl, 1lp, let A1 ... Ap be the actual type arguments inferred (§15.12.2.7) for this invocation under the initial constraints Ui << Ti, 1ik-1, Uk << Ti, kin and let Si = Ti[R1 = A1, ..., Rp = Ap] 1in; otherwise let Si = Ti, 1in. Then:
      for all j from 1 to k-1 , Uj <: Sj, and,
      for all j from k to n , Uk <: Sj, and,
      If the second method is a generic method as described above then Al <: Bl[R1 = A1, ..., Rp = Ap], 1lp.

Ignoring the issue generics, does this mean varargs is more important than subtyping, or subtyping is more important than varargs, when deciding whether one method is more specific than another? I can't figure it out.

Concrete example: Which of the following compute() methods is "more specific" according to the JLS?

package com.example.test.reflect;

class JLS15Test
{
    int compute(Object o1, Object o2, Object... others) { return 1; }
    int compute(String s1, Object... others)            { return 2; }

    public static void main(String[] args)
    {
        JLS15Test y = new JLS15Test();
        System.out.println(y.compute(y,y,y));
        System.out.println(y.compute("hi",y,y));
    }
}

I can't figure out which is "more specific"; the output prints

1
2

I'm confused how to interpret the results. When the first argument was a String, the compiler picked the method with the more specific subtype. When the first argument was an Object, the compiler picked the method with the fewer number of optional varargs.

NOTE: If you are not reading this section of the JLS, and you are giving an answer that depends on the types of the arguments, you are not helping me. If you carefully read the JLS, other than the parts relating to generics, the definition of "more specific" depends on the declared arguments, not on the actual arguments -- this comes into play in other parts of the JLS (can't find it at the moment).

e.g. for fixed arity methods, compute(String s) would be more specific than compute(Object o). But I'm trying to understand the relevant section of the JLS re: variable arity methods.

Body:
int compute(String s1, Object... others) is more specific when you call compute("hi",y,y), since String is a subclass of Object.

int compute(Object o1, Object o2, Object... others) is the only match for compute(y,y,y) because the second method receives String as first param, and JLS15Test is not a subclass of String

EDIT

My answer resides on the basics of specific methods, but your code only compiles because of the ability of the compiler to distinguish between the methods in the way described above.

The following examples will not even compile because of its ambiguity:

case 1:

int compute(Object o1, Object o2, Object... others) { return 1; }
int compute(Object s1, Object... others)            { return 2; }

public static void main(String[] args)
{
    JLS15Test y = new JLS15Test();
    System.out.println(y.compute(y,y,y));
    System.out.println(y.compute("hi",y,y));
}

case 2:

int compute(String o1, Object o2, Object... others) { return 1; }
int compute(Object s1, String... others)            { return 2; }

public static void main(String[] args)
{
    JLS15Test y = new JLS15Test();
    System.out.println(y.compute("hi","hi","hi"));
}

More Edit

I didn't get your question well the first two times (and I hope I do this time :) ).

The actual case you are talking about will look like that:

public class Test {
    public static void main(String[] args)
    {
        Test t = new Test();
        int a = t.compute("t", new Test());
        System.out.println(a);
    }

    int compute(String s, Object... others) { return 1; }
    int compute(Object s1, Object others)   { return 2; }
}

In this case, compute(Object s1, Object others) is indeed more specific then compute(String s, Object... others) (has less parameters) so the output will be 2 indeed.