问:
AVPlayer Cannot dismiss the View
I am creating a feature that allows users to watch video.

With the code below it animate the video player onto the screen and it include an AVPlayer into the video view and start playing video clip.

However when I press dismissButton it does not work. It only hides dismissButton.

I appreciate any help that lead me to solve this problem.

```<code>import UIKit
import AVFoundation

class VideoPlayerView: UIView {

    let activityIndicatorView: UIActivityIndicatorView = {
        let aiv = UIActivityIndicatorView(activityIndicatorStyle: .whiteLarge)
        aiv.translatesAutoresizingMaskIntoConstraints = false
        aiv.startAnimating()
        return aiv
    }()

    lazy var pausePlayButton: UIButton = {
        let button = UIButton(type: .system)
        let image = UIImage(named: "pauseButton")
        button.setImage(image, for: UIControlState())
        button.translatesAutoresizingMaskIntoConstraints = false
        button.tintColor = .white
        button.isHidden = true

        button.addTarget(self, action: #selector(handlePause), for: .touchUpInside)

        return button
    }()

    var isPlaying = false

    func handlePause() {
        if isPlaying {
            player?.pause()
            pausePlayButton.setImage(UIImage(named: "playVideoButton"), for: UIControlState())
        } else {
            player?.play()
            pausePlayButton.setImage(UIImage(named: "pauseButton"), for: UIControlState())
        }

        isPlaying = !isPlaying
    }

    let controlsContainerView: UIView = {
        let view = UIView()
        view.backgroundColor = UIColor(white: 0, alpha: 1)
        return view
    }()

    let dismissButton: UIButton = {
        let button = UIButton(type: .system)
        let image = UIImage(named: "closeVideoButton")
        button.setImage(image, for: UIControlState())
        button.translatesAutoresizingMaskIntoConstraints = false
        button.tintColor = .white
        button.addTarget(self, action:#selector(pressButton(button:)), for: .touchUpInside)

        return button
    }()

    func pressButton(button: UIButton) {
        controlsContainerView.removeFromSuperview()

        self.removeFromSuperview()
    }

    let currentTimeLabel: UILabel = {
        let label = UILabel()
        label.translatesAutoresizingMaskIntoConstraints = false
        label.text = "0:00"
        label.textColor = .white
        label.font = UIFont.boldSystemFont(ofSize: 17)
        return label
    }()

    lazy var videoSlider: UISlider = {
        let slider = UISlider()
        slider.translatesAutoresizingMaskIntoConstraints = false
        slider.minimumTrackTintColor = .white
        slider.maximumTrackTintColor = .lightGray
        slider.setThumbImage(UIImage(named: "thumb"), for: UIControlState())

        slider.addTarget(self, action: #selector(handleSliderChange), for: .valueChanged)

        return slider
    }()

    func handleSliderChange() {
        print(videoSlider.value)

        if let duration = player?.currentItem?.duration {
            let totalSeconds = CMTimeGetSeconds(duration)

            let value = Float64(videoSlider.value) * totalSeconds

            let seekTime = CMTime(value: Int64(value), timescale: 1)

            player?.seek(to: seekTime, completionHandler: { (completedSeek) in
            })
        }
    }

    override init(frame: CGRect) {
        super.init(frame: frame)

        setupPlayerView()

        setupGradientLayer()

        controlsContainerView.frame = frame
        addSubview(controlsContainerView)

        controlsContainerView.addSubview(activityIndicatorView)
        activityIndicatorView.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
        activityIndicatorView.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true

        controlsContainerView.addSubview(pausePlayButton)
        pausePlayButton.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
        pausePlayButton.rightAnchor.constraint(equalTo: rightAnchor).isActive = true
        pausePlayButton.leftAnchor.constraint(equalTo: leftAnchor).isActive = true
        pausePlayButton.heightAnchor.constraint(equalToConstant: 50).isActive = true

        controlsContainerView.addSubview(currentTimeLabel)
        currentTimeLabel.rightAnchor.constraint(equalTo: rightAnchor, constant: -8).isActive = true
        currentTimeLabel.topAnchor.constraint(equalTo: topAnchor, constant: -2).isActive = true
        currentTimeLabel.widthAnchor.constraint(equalToConstant: 50).isActive = true
        currentTimeLabel.heightAnchor.constraint(equalToConstant: 44).isActive = true

        controlsContainerView.addSubview(dismissButton)
        dismissButton.leftAnchor.constraint(equalTo: leftAnchor, constant: 8).isActive = true
        dismissButton.topAnchor.constraint(equalTo: topAnchor, constant: -2).isActive = true
        dismissButton.widthAnchor.constraint(equalToConstant: 50).isActive = true
        dismissButton.heightAnchor.constraint(equalToConstant: 44).isActive = true

        controlsContainerView.addSubview(videoSlider)
        videoSlider.rightAnchor.constraint(equalTo: currentTimeLabel.leftAnchor).isActive = true
        videoSlider.topAnchor.constraint(equalTo: topAnchor).isActive = true
        videoSlider.leftAnchor.constraint(equalTo: dismissButton.rightAnchor).isActive = true
        videoSlider.heightAnchor.constraint(equalToConstant: 40).isActive = true

        backgroundColor = .black
    }

    var player: AVPlayer?

    fileprivate func setupPlayerView() {
        let urlString = "https://firebasestorage.googleapis.com/v0/b/bunpou-d20ae.appspot.com/o/katoomouto.mp4?alt=media&token=861a0bad-2979-428c-94cf-f86dc9cb63ca"
        if let url = URL(string: urlString) {
            player = AVPlayer(url: url)

            let playerLayer = AVPlayerLayer(player: player)
            self.layer.addSublayer(playerLayer)
            playerLayer.frame = self.frame

            player?.play()

            player?.addObserver(self, forKeyPath: "currentItem.loadedTimeRanges", options: .new, context: nil)

            //track player progress

            let interval = CMTime(value: 1, timescale: 2)
            player?.addPeriodicTimeObserver(forInterval: interval, queue: DispatchQueue.main, using: { (progressTime) in

                let seconds = CMTimeGetSeconds(progressTime)
                let secondsString = String(format: "%02d", Int(seconds.truncatingRemainder(dividingBy: 60)))
                let minutesString = String(format: "%02d", Int(seconds / 60))

                self.currentTimeLabel.text = "\(minutesString):\(secondsString)"

                if let duration = self.player?.currentItem?.duration {
                    let durationSeconds = CMTimeGetSeconds(duration)

                    self.videoSlider.value = Float(seconds / durationSeconds)

                }

            })
        }
    }

    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {

        //this is when the player is ready and rendering frames
        if keyPath == "currentItem.loadedTimeRanges" {
            activityIndicatorView.stopAnimating()
            controlsContainerView.backgroundColor = .clear
            pausePlayButton.isHidden = false
            isPlaying = true

        }
    }

    fileprivate func setupGradientLayer() {
        let gradientLayer = CAGradientLayer()
        gradientLayer.frame = bounds
        gradientLayer.colors = [UIColor.black.cgColor, UIColor.clear.cgColor]
        gradientLayer.locations = [-1.4, 0.2]
        controlsContainerView.layer.addSublayer(gradientLayer)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

class VideoLauncher: NSObject {

    func showVideoPlayer() {
        print("Showing video player animation....")

        if let keyWindow = UIApplication.shared.keyWindow {
            let view = UIView(frame: keyWindow.frame)
            view.backgroundColor = UIColor.white

            view.frame = CGRect(x: keyWindow.frame.width - 10, y: keyWindow.frame.height - 10, width: 10, height: 10)

            let videoPlayerFrame = CGRect(x: 0, y: 0, width: keyWindow.frame.width, height: keyWindow.frame.height)
            let videoPlayerView = VideoPlayerView(frame: videoPlayerFrame)
            view.addSubview(videoPlayerView)

            keyWindow.addSubview(view)

            UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: {

                view.frame = keyWindow.frame

            }, completion: { (completedAnimation) in
            })
        }
    }
}
</code>```

答:
When dismiss button is tapped you remove only controlsContainerView from the superview.

```<code>func pressButton(button: UIButton) { controlsContainerView.removeFromSuperview() }
</code>```

Given how you have things setup I would do the following:

you do not need let view = ... inside showVideoPlayer, but just use videoPlayerView and add it like keyWindow.addSubView(videoPlayerView)

Inside pressButton you have to first remove observers from player that you added like player?.addObserver(self, forKeyPath: "currentItem.loadedTimeRanges", options: .new, context: nil)

still inside pressButton stop the player like player?.stop() and then remove self from superview like you are doing with self.removeFromSuperview()

Notes: I dont like that view itself should be responsible to remove itself from superview. So I would suggest that you have a controller that handles showing/hiding of VideoPlayerView and just add a public method to VideoPlayerView like stop where you would remove all observers of the player, stop the player so that when controller decides to remove VideoPlayerView you will do a nice cleanup

Title: AVPlayer Cannot dismiss the View

Body:
I am creating a feature that allows users to watch video.

With the code below it animate the video player onto the screen and it include an AVPlayer into the video view and start playing video clip.

However when I press dismissButton it does not work. It only hides dismissButton.

I appreciate any help that lead me to solve this problem.

import UIKit
import AVFoundation

class VideoPlayerView: UIView {

    let activityIndicatorView: UIActivityIndicatorView = {
        let aiv = UIActivityIndicatorView(activityIndicatorStyle: .whiteLarge)
        aiv.translatesAutoresizingMaskIntoConstraints = false
        aiv.startAnimating()
        return aiv
    }()

    lazy var pausePlayButton: UIButton = {
        let button = UIButton(type: .system)
        let image = UIImage(named: "pauseButton")
        button.setImage(image, for: UIControlState())
        button.translatesAutoresizingMaskIntoConstraints = false
        button.tintColor = .white
        button.isHidden = true

        button.addTarget(self, action: #selector(handlePause), for: .touchUpInside)

        return button
    }()

    var isPlaying = false

    func handlePause() {
        if isPlaying {
            player?.pause()
            pausePlayButton.setImage(UIImage(named: "playVideoButton"), for: UIControlState())
        } else {
            player?.play()
            pausePlayButton.setImage(UIImage(named: "pauseButton"), for: UIControlState())
        }

        isPlaying = !isPlaying
    }

    let controlsContainerView: UIView = {
        let view = UIView()
        view.backgroundColor = UIColor(white: 0, alpha: 1)
        return view
    }()

    let dismissButton: UIButton = {
        let button = UIButton(type: .system)
        let image = UIImage(named: "closeVideoButton")
        button.setImage(image, for: UIControlState())
        button.translatesAutoresizingMaskIntoConstraints = false
        button.tintColor = .white
        button.addTarget(self, action:#selector(pressButton(button:)), for: .touchUpInside)

        return button
    }()

    func pressButton(button: UIButton) {
        controlsContainerView.removeFromSuperview()

        self.removeFromSuperview()
    }

    let currentTimeLabel: UILabel = {
        let label = UILabel()
        label.translatesAutoresizingMaskIntoConstraints = false
        label.text = "0:00"
        label.textColor = .white
        label.font = UIFont.boldSystemFont(ofSize: 17)
        return label
    }()

    lazy var videoSlider: UISlider = {
        let slider = UISlider()
        slider.translatesAutoresizingMaskIntoConstraints = false
        slider.minimumTrackTintColor = .white
        slider.maximumTrackTintColor = .lightGray
        slider.setThumbImage(UIImage(named: "thumb"), for: UIControlState())

        slider.addTarget(self, action: #selector(handleSliderChange), for: .valueChanged)

        return slider
    }()

    func handleSliderChange() {
        print(videoSlider.value)

        if let duration = player?.currentItem?.duration {
            let totalSeconds = CMTimeGetSeconds(duration)

            let value = Float64(videoSlider.value) * totalSeconds

            let seekTime = CMTime(value: Int64(value), timescale: 1)

            player?.seek(to: seekTime, completionHandler: { (completedSeek) in
            })
        }
    }

    override init(frame: CGRect) {
        super.init(frame: frame)

        setupPlayerView()

        setupGradientLayer()

        controlsContainerView.frame = frame
        addSubview(controlsContainerView)

        controlsContainerView.addSubview(activityIndicatorView)
        activityIndicatorView.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
        activityIndicatorView.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true

        controlsContainerView.addSubview(pausePlayButton)
        pausePlayButton.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
        pausePlayButton.rightAnchor.constraint(equalTo: rightAnchor).isActive = true
        pausePlayButton.leftAnchor.constraint(equalTo: leftAnchor).isActive = true
        pausePlayButton.heightAnchor.constraint(equalToConstant: 50).isActive = true

        controlsContainerView.addSubview(currentTimeLabel)
        currentTimeLabel.rightAnchor.constraint(equalTo: rightAnchor, constant: -8).isActive = true
        currentTimeLabel.topAnchor.constraint(equalTo: topAnchor, constant: -2).isActive = true
        currentTimeLabel.widthAnchor.constraint(equalToConstant: 50).isActive = true
        currentTimeLabel.heightAnchor.constraint(equalToConstant: 44).isActive = true

        controlsContainerView.addSubview(dismissButton)
        dismissButton.leftAnchor.constraint(equalTo: leftAnchor, constant: 8).isActive = true
        dismissButton.topAnchor.constraint(equalTo: topAnchor, constant: -2).isActive = true
        dismissButton.widthAnchor.constraint(equalToConstant: 50).isActive = true
        dismissButton.heightAnchor.constraint(equalToConstant: 44).isActive = true

        controlsContainerView.addSubview(videoSlider)
        videoSlider.rightAnchor.constraint(equalTo: currentTimeLabel.leftAnchor).isActive = true
        videoSlider.topAnchor.constraint(equalTo: topAnchor).isActive = true
        videoSlider.leftAnchor.constraint(equalTo: dismissButton.rightAnchor).isActive = true
        videoSlider.heightAnchor.constraint(equalToConstant: 40).isActive = true

        backgroundColor = .black
    }

    var player: AVPlayer?

    fileprivate func setupPlayerView() {
        let urlString = "https://firebasestorage.googleapis.com/v0/b/bunpou-d20ae.appspot.com/o/katoomouto.mp4?alt=media&token=861a0bad-2979-428c-94cf-f86dc9cb63ca"
        if let url = URL(string: urlString) {
            player = AVPlayer(url: url)

            let playerLayer = AVPlayerLayer(player: player)
            self.layer.addSublayer(playerLayer)
            playerLayer.frame = self.frame

            player?.play()

            player?.addObserver(self, forKeyPath: "currentItem.loadedTimeRanges", options: .new, context: nil)

            //track player progress

            let interval = CMTime(value: 1, timescale: 2)
            player?.addPeriodicTimeObserver(forInterval: interval, queue: DispatchQueue.main, using: { (progressTime) in

                let seconds = CMTimeGetSeconds(progressTime)
                let secondsString = String(format: "%02d", Int(seconds.truncatingRemainder(dividingBy: 60)))
                let minutesString = String(format: "%02d", Int(seconds / 60))

                self.currentTimeLabel.text = "\(minutesString):\(secondsString)"

                if let duration = self.player?.currentItem?.duration {
                    let durationSeconds = CMTimeGetSeconds(duration)

                    self.videoSlider.value = Float(seconds / durationSeconds)

                }

            })
        }
    }

    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {

        //this is when the player is ready and rendering frames
        if keyPath == "currentItem.loadedTimeRanges" {
            activityIndicatorView.stopAnimating()
            controlsContainerView.backgroundColor = .clear
            pausePlayButton.isHidden = false
            isPlaying = true

        }
    }

    fileprivate func setupGradientLayer() {
        let gradientLayer = CAGradientLayer()
        gradientLayer.frame = bounds
        gradientLayer.colors = [UIColor.black.cgColor, UIColor.clear.cgColor]
        gradientLayer.locations = [-1.4, 0.2]
        controlsContainerView.layer.addSublayer(gradientLayer)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

class VideoLauncher: NSObject {

    func showVideoPlayer() {
        print("Showing video player animation....")

        if let keyWindow = UIApplication.shared.keyWindow {
            let view = UIView(frame: keyWindow.frame)
            view.backgroundColor = UIColor.white

            view.frame = CGRect(x: keyWindow.frame.width - 10, y: keyWindow.frame.height - 10, width: 10, height: 10)

            let videoPlayerFrame = CGRect(x: 0, y: 0, width: keyWindow.frame.width, height: keyWindow.frame.height)
            let videoPlayerView = VideoPlayerView(frame: videoPlayerFrame)
            view.addSubview(videoPlayerView)

            keyWindow.addSubview(view)

            UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: {

                view.frame = keyWindow.frame

            }, completion: { (completedAnimation) in
            })
        }
    }
}

Body:
When dismiss button is tapped you remove only controlsContainerView from the superview.

func pressButton(button: UIButton) { controlsContainerView.removeFromSuperview() }

Given how you have things setup I would do the following:

you do not need let view = ... inside showVideoPlayer, but just use videoPlayerView and add it like keyWindow.addSubView(videoPlayerView)

Inside pressButton you have to first remove observers from player that you added like player?.addObserver(self, forKeyPath: "currentItem.loadedTimeRanges", options: .new, context: nil)

still inside pressButton stop the player like player?.stop() and then remove self from superview like you are doing with self.removeFromSuperview()

Notes: I dont like that view itself should be responsible to remove itself from superview. So I would suggest that you have a controller that handles showing/hiding of VideoPlayerView and just add a public method to VideoPlayerView like stop where you would remove all observers of the player, stop the player so that when controller decides to remove VideoPlayerView you will do a nice cleanup


来源: stackexchange

问:
Database Multiple Table Join Queries
I really don't know what queries to be combined using these table to achieve my coressponding output please assist me

Table 1

w_ref   t_id   q_id  qty

110     111    500   1

111     112    500   2

112     113    500   3

Table 2

t_id q_id  material-x  material-y material_id

111  500      14          15          7

112  500      18          18          7

113  500      10          11          8

Table 3

id   material_name

7    abc

 8    def

I expect that joining table output like this

Output

w_ref   qty  material-x   material-y  material_name

110     1      14          15           abc

111     2      18          07           abc

112     3      10          11           def

答:
Here is a simple example of a SQL of a INNER JOIN. This will give you a basic understanding from the results given.

```<code>SELECT a.w_ref, a.t_id, a.q_id, a.qty, b.material-x FROM table1 a INNER JOIN table2 b ON b.t_id = a.t_id;
</code>```

However their is very little of what you're trying to achieve and should not just post a question asking someone to sort it. Maybe add what you have tried so far and what outcomes you have had.

ContentLicense: CC BY-SA 3.0

Title: Database Multiple Table Join Queries

Body:
Here is a simple example of a SQL of a INNER JOIN. This will give you a basic understanding from the results given.

SELECT a.w_ref, a.t_id, a.q_id, a.qty, b.material-x FROM table1 a INNER JOIN table2 b ON b.t_id = a.t_id;

However their is very little of what you're trying to achieve and should not just post a question asking someone to sort it. Maybe add what you have tried so far and what outcomes you have had.


问:
A better way to show different wpf pages in mainWindow?
I have several Wpf pages in my project, these pages have different forms and ui control indide theme. The image below shows the mainWindow and there are two button.
I want to show a specific page when I click on + or Edit button using the Frame control which is highlighted.

apparenatly this woks:

```<code>Page1 me = new Page1();
mainFrame.Content = me;
</code>```

But it has an IE navigation sound and a toolbar appears after going to page2.
any better way to show diffrent pages and not using a frame?

答: You may want to convert the Page into a UserControl.  You can then put that control inside some other container, such as a Grid.  You'll have to manually swap out the pages in the container when navigating, but it looks like you're doing that anyway.

Body:
I have several Wpf pages in my project, these pages have different forms and ui control indide theme. The image below shows the mainWindow and there are two button.
I want to show a specific page when I click on + or Edit button using the Frame control which is highlighted.

apparenatly this woks:

Page1 me = new Page1();
mainFrame.Content = me;

But it has an IE navigation sound and a toolbar appears after going to page2.
any better way to show diffrent pages and not using a frame?

ContentLicense: CC BY-SA 2.5


问:
I have an input form with a prepaired statement that should input into sql and print the input but all I get is NULL printed on the page
I have an input form with a prepaired statement that should input into sql and print the input but all I get is a blank page with the input php address. Have i missed something? I have changed the code to below but all that appears is NULL. The date field is sql type date and the string i entered into it to test is "2008-11-11", without the quotes of course.

```<code>        <?php
function shutdown(){
  var_dump(error_get_last());
}

register_shutdown_function('shutdown');
session_start();
error_reporting(E_ALL);
ini_set('display_errors', 1);
include("dbconfig.php");
$errorvar = "";
if (isset($_POST['submit'])) {
    if (empty($_POST['Title']) || empty($_POST["Date"]) || empty($_POST["Country"]) || empty($_POST["bloguser"]) || empty($_POST["Blogentry"])) {
        $errorvar = "You dun gooffed";
        echo $errorvar;
    } else {
        //defining and injection protecting data
        $title = $_POST['Title'];
        $date = $_POST['Date'];
        $country = $_POST['Country'];
        $bloguser = $_POST['bloguser'];
        $blogentry = $_POST['Blogentry'];

    $stmt = $mysqli->prepare("INSERT INTO blogs (BlogName,blogDate,country,bloguser,Blogdata) VALUES (?,?,?,?,?)");

        $stmt->bind_param('sssss', $title, $date, $country, $bloguser, $blogentry);

        if ($stmt->execute()) {
            echo "New records created successfully";
            printf("%d Row inserted.\n", $stmt->affected_rows);
            header("location:index.php");
        } else {
        header("location:index.php");
            echo $conn->error;
        }
        $stmt->close();
        $conn->close();
        header("location:index.php");
    }
}
?>
</code>```

The html form is below

```<code>   <fieldset style="width:45%"><legend>Blog data entry</legend>
        <form name="Blogentry" action="Inputform.php" method="POST">
            <label for="Title">Title: </label>
            <input type="text" name="Title" value="" size="40"/><br>
            <label for="Date">Date: </label>
            <input type="text" name="Date" value="" size="40"/><br>
            <label for="Country">Country: </label>
            <input type="text" name="Country" value="" size="40"/><br>
            <label for="bloguser">User: </label>
            <input type="text" name="bloguser" value="" size="40"/><br>
            <label for="Blogentry">Blog: </label>
            <textarea name="Blogentry" rows="4" cols="20">
            </textarea><br>
            <input id="button" type="submit" name="submitblog" value="submit-blog">
        </form>
            </fieldset>
    </body>
</html>
</code>```

答:
enable error reporting :
add on top of your script

```<code>error_reporting(E_ALL);
ini_set('display_errors', 1);
</code>```

and then use prepared statements proper. As far as your script there no parameters that you are binding,

```<code><?php
session_start();
include("dbconfig.php");
$errorvar = "";
if (isset($_POST['submit'])) {
    if (empty($_POST['Title']) || empty($_POST["Date"]) || empty($_POST["Country"]) || empty($_POST["bloguser"]) || empty($_POST["Blogentry"])) {
        $errorvar = "You dun gooffed";
        echo $errorvar;
    } else {
        //defining and injection protecting data
        $title     = $_POST['Title'];
        $date      = $_POST['Date'];
        $country   = $_POST['Country'];
        $bloguser  = $_POST['bloguser'];
        $blogentry = $_POST['Blogentry'];

        $stmt = $conn->prepare("INSERT INTO blogs (BlogName,blogDate,country,bloguser,Blogdata) VALUES (?,?,?,?,?)");

        $stmt->bind_param("sssss", $title, $date, $country, $bloguser, $blogentry);

        if ($stmt->execute()) {
            echo "New records created successfully";
            printf("%d Row inserted.\n", $stmt->affected_rows);
            header("location:index.php");

        } else {

            echo $conn->error;
        }
        $stmt->close();
        $conn->close();
    }
}
?>
</code>```

Body:
I have an input form with a prepaired statement that should input into sql and print the input but all I get is a blank page with the input php address. Have i missed something? I have changed the code to below but all that appears is NULL. The date field is sql type date and the string i entered into it to test is "2008-11-11", without the quotes of course.

        <?php
function shutdown(){
  var_dump(error_get_last());
}

register_shutdown_function('shutdown');
session_start();
error_reporting(E_ALL);
ini_set('display_errors', 1);
include("dbconfig.php");
$errorvar = "";
if (isset($_POST['submit'])) {
    if (empty($_POST['Title']) || empty($_POST["Date"]) || empty($_POST["Country"]) || empty($_POST["bloguser"]) || empty($_POST["Blogentry"])) {
        $errorvar = "You dun gooffed";
        echo $errorvar;
    } else {
        //defining and injection protecting data
        $title = $_POST['Title'];
        $date = $_POST['Date'];
        $country = $_POST['Country'];
        $bloguser = $_POST['bloguser'];
        $blogentry = $_POST['Blogentry'];

    $stmt = $mysqli->prepare("INSERT INTO blogs (BlogName,blogDate,country,bloguser,Blogdata) VALUES (?,?,?,?,?)");

        $stmt->bind_param('sssss', $title, $date, $country, $bloguser, $blogentry);

        if ($stmt->execute()) {
            echo "New records created successfully";
            printf("%d Row inserted.\n", $stmt->affected_rows);
            header("location:index.php");
        } else {
        header("location:index.php");
            echo $conn->error;
        }
        $stmt->close();
        $conn->close();
        header("location:index.php");
    }
}
?>

The html form is below

   <fieldset style="width:45%"><legend>Blog data entry</legend>
        <form name="Blogentry" action="Inputform.php" method="POST">
            Title:
            <input type="text" name="Title" value="" size="40"/>

            Date:
            <input type="text" name="Date" value="" size="40"/>

            Country:
            <input type="text" name="Country" value="" size="40"/>

            User:
            <input type="text" name="bloguser" value="" size="40"/>

            Blog:
            <textarea name="Blogentry" rows="4" cols="20">
            </textarea>

            <input id="button" type="submit" name="submitblog" value="submit-blog">
        </form>
            </fieldset>

Body:
enable error reporting :
add on top of your script

error_reporting(E_ALL);
ini_set('display_errors', 1);

and then use prepared statements proper. As far as your script there no parameters that you are binding,

<?php
session_start();
include("dbconfig.php");
$errorvar = "";
if (isset($_POST['submit'])) {
    if (empty($_POST['Title']) || empty($_POST["Date"]) || empty($_POST["Country"]) || empty($_POST["bloguser"]) || empty($_POST["Blogentry"])) {
        $errorvar = "You dun gooffed";
        echo $errorvar;
    } else {
        //defining and injection protecting data
        $title     = $_POST['Title'];
        $date      = $_POST['Date'];
        $country   = $_POST['Country'];
        $bloguser  = $_POST['bloguser'];
        $blogentry = $_POST['Blogentry'];

        $stmt = $conn->prepare("INSERT INTO blogs (BlogName,blogDate,country,bloguser,Blogdata) VALUES (?,?,?,?,?)");

        $stmt->bind_param("sssss", $title, $date, $country, $bloguser, $blogentry);

        if ($stmt->execute()) {
            echo "New records created successfully";
            printf("%d Row inserted.\n", $stmt->affected_rows);
            header("location:index.php");

        } else {

            echo $conn->error;
        }
        $stmt->close();
        $conn->close();
    }
}
?>


问:
Extracting sub arrays from a two dimensional array for each element and displaying them in a table using KnockoutJS
I have used below code in PHP to extract data from MySQL :

```<code><?php
require("connect.php");
$sql = "SELECT `inn_lay_list`, `inner_layer` FROM `da_customer_auto_inner`
where `mpcode` = 'qf017'";
$result = mysqli_query($conn,$sql);
while($row = mysqli_fetch_assoc($result)) {
    $data1 = $row['inn_lay_list'];
    $data2 = $row['inner_layer'];
}

$parts1 = explode(';',$data1);
$parts2 = explode(';',$data2);
$layer_cnt = count($parts1);
$array_inner = array_chunk($parts2, 8);

echo json_encode($parts1);
echo json_encode($array_inner);

mysqli_close($conn);
?>
</code>```

I obtained the result as:

["001","011","021","031"]

[["1","2","3","4","5","6","7","8"], ["11","12","13","14","15","16","17","18"], ["21","22","23","24","25","26","27","28"],[31","32","33","34","35","36","37","38"]]

Here for each element in first array there is a sub array in the second array(two dimensional array).
Now I want to display this in HTML page using a table. I am trying to use KnockoutJS “foreach” option with a named template:

```<code><script>
function MyViewModel() {
    this.layer = [{
        name: "<?=@$parts1[0]?>",
        layer_data: "<?=@$array_inner[0]?>"
    },
    {
        name: "<?=@$parts1[1]?>",
        layer_data: "<?=@$array_inner[1]?>"
    },
    {
        name: "<?=@$parts1[2]?>",
        layer_data: "<?=@$array_inner[2]?>"
    },
    {
        name: "<?=@$parts1[3]?>",
        layer_data: "<?=@$array_inner[3]?>"
    }]
}
ko.applyBindings(new MyViewModel());
</script>

<table class="table table-bordered">
    <thead>
    <tr>
      <td>Layer</td>
      <td>P2P</td>
      <td>P2T</td>
      <td>T2T</td>
      <td>Track Width</td>
      <td>PTH To Cu</td>
      <td>NPTH To Cu</td>
      <td>PTH AR</td>
      <td>Via AR</td>
    </tr>
    </thead>
    <tbody data-bind="template:{name:'layer-template', foreach:layer}">
    </tbody>
</table>
<script type="text/html" id="layer-template">
<tr>
    <td data-bind="text: name"></td>
    <td data-bind="text: layer_data[0]"></td>
    <td data-bind="text: layer_data[1]"></td>
    <td data-bind="text: layer_data[2]"></td>
    <td data-bind="text: layer_data[3]"></td>
    <td data-bind="text: layer_data[4]"></td>
    <td data-bind="text: layer_data[5]"></td>
    <td data-bind="text: layer_data[6]"></td>
    <td data-bind="text: layer_data[7]"></td>
</tr>
</script>
</code>```

I want my output as below :

ContentLicense: CC BY-SA 4.0

Body:
I have used below code in PHP to extract data from MySQL :

<?php
require("connect.php");
$sql = "SELECT `inn_lay_list`, `inner_layer` FROM `da_customer_auto_inner`
where `mpcode` = 'qf017'";
$result = mysqli_query($conn,$sql);
while($row = mysqli_fetch_assoc($result)) {
    $data1 = $row['inn_lay_list'];
    $data2 = $row['inner_layer'];
}

$parts1 = explode(';',$data1);
$parts2 = explode(';',$data2);
$layer_cnt = count($parts1);
$array_inner = array_chunk($parts2, 8);

echo json_encode($parts1);
echo json_encode($array_inner);

mysqli_close($conn);
?>

I obtained the result as:

["001","011","021","031"]

[["1","2","3","4","5","6","7","8"], ["11","12","13","14","15","16","17","18"], ["21","22","23","24","25","26","27","28"],[31","32","33","34","35","36","37","38"]]

Here for each element in first array there is a sub array in the second array(two dimensional array).
Now I want to display this in HTML page using a table. I am trying to use KnockoutJS “foreach” option with a named template:

      Layer
      P2P
      P2T
      T2T
      Track Width
      PTH To Cu
      NPTH To Cu
      PTH AR
      Via AR

I want my output as below :

Body:
Just do the following :

$array = [[1,2,3], [4,5,6], [7,8,9]];
$array[0];


问:
Spring boot running from Eclipse vs running from Terminal [Not Loading properties file]
I am working on spring boot application in which I have made a property file,

application.properties

```<code>#Generated by Eclipse Messages Editor (Eclipse Babel)
# ===============================
# = Spring Application
# ===============================

server.port = 80
</code>```

and here is main method:

```<code>public static void main(String[] args) throws Exception {
    new SpringApplicationBuilder().sources(SpringBootWebApplication.class).properties(System.getProperties()).run(args);
}
</code>```

it is working fine when I am running it on eclipse.

if when I am running using commandline:

```<code>java -jar target\tmfboot-0.0.1-SNAPSHOT.jar
</code>```

application is running on default port of tomcat 8080

I think it is not loading application.properties file while running using terminal.

I’m using Maven 3.2.

答:
change your main method as follows, it will load the application.properties from src/main/resources folder

```<code>public static void main(String[] args) throws Exception {
   SpringApplication.run(Application.class, args);
}
</code>```

Body:
I am working on spring boot application in which I have made a property file,

application.properties

#Generated by Eclipse Messages Editor (Eclipse Babel)
# ===============================
# = Spring Application
# ===============================

server.port = 80

and here is main method:

public static void main(String[] args) throws Exception {
    new SpringApplicationBuilder().sources(SpringBootWebApplication.class).properties(System.getProperties()).run(args);
}

it is working fine when I am running it on eclipse.

if when I am running using commandline:

java -jar target\tmfboot-0.0.1-SNAPSHOT.jar

application is running on default port of tomcat 8080

I think it is not loading application.properties file while running using terminal.

I’m using Maven 3.2.

Body:
change your main method as follows, it will load the application.properties from src/main/resources folder

public static void main(String[] args) throws Exception {
   SpringApplication.run(Application.class, args);
}


问:
Add "where" query in Sequalize based on flag
I want to add "where" query in Sequalize based on flag . Let me know how to get this.

For example if the flag is true then I want to add this "where" class otherwise I don't want to add the "where" clause.

```<code>models.Users.findAll({
        where: {
            email: req.query.email
        }
    }).then(function (list) {
        res.send(list);
    }).catch(function (error) {
        res.status(500).json(error);
    });

models.Users.findAll({
    }).then(function (list) {
        res.send(list);
    }).catch(function (error) {
        res.status(500).json(error);
    });
</code>```

答:
You can create JSON first which you are providing in where clause and then pass it in where clause.. something like

```<code>var jsonObj = null ;

if (req.query.email){
   jsonObj =  {"email": req.query.email};
} else {
   jsonObj =  {"email": {$ne:null}}; //otherwise it will return all rows, if email is not null in your database
}

models.Users.findAll({
        where: jsonObj
    }).then(function (list) {
        res.send(list);
    }).catch(function (error) {
        res.status(500).json(error);
    });
</code>```

Hope this will help

Body:
I want to add "where" query in Sequalize based on flag . Let me know how to get this.

For example if the flag is true then I want to add this "where" class otherwise I don't want to add the "where" clause.

models.Users.findAll({
        where: {
            email: req.query.email
        }
    }).then(function (list) {
        res.send(list);
    }).catch(function (error) {
        res.status(500).json(error);
    });

models.Users.findAll({
    }).then(function (list) {
        res.send(list);
    }).catch(function (error) {
        res.status(500).json(error);
    });

Body:
You can create JSON first which you are providing in where clause and then pass it in where clause.. something like

var jsonObj = null ;

if (req.query.email){
   jsonObj =  {"email": req.query.email};
} else {
   jsonObj =  {"email": {$ne:null}}; //otherwise it will return all rows, if email is not null in your database
}

models.Users.findAll({
        where: jsonObj
    }).then(function (list) {
        res.send(list);
    }).catch(function (error) {
        res.status(500).json(error);
    });

Hope this will help


问:
get substring from string in C
I am trying to write a program in C, which will allow me to get a string I want between two other strings that will be defined. To be more specific, my example string is

```<code> "blahblah<mailto:agent007@example.org>blahblahblah"
</code>```

and I need to be able to extract the "agent007" substring to a new variable. I have tried the strtok() method, but the thing is I can't extract the tokens to a new variable or an array. I have tokenized the string and the statement that would suite me fine would be something like " if token[i] == "mailto" && token[i+2] == "example" then mailAdd = token[i+1] " (in a pseudo-code way :) )

my program so far

```<code>#include <stdio.h>
#include <string.h>

int main ()
{
  char str[] ="blahblah<mailto:agent007@example.org>blahblahblah";
  char * tch;
  tch = strtok (str,"<:@");
  while (tch != NULL)
  {
    printf ("%s\n",tch);
    tch = strtok (NULL, "<:@");
  }
  return 0;
}
</code>```

Of course, any other suggestion beyond tokens will be greatly appreciated -

答:
My first thought was to use strstr for "mailto:" and strchr for the '@'

```<code>// pseudo code
char *mailto = strstr(src, "mailto:"); // possibly convert src to lowercase
char *atsign = strchr(mailto, '@');
while (mailto < atsign) *dst++ = *mailto++;
</code>```

Of course that is a very rough draft. It needs lots of refining (failure to find the "mailto:" string or '@' char, error-checking, special cases, tests, ...)

Saving the strtok pointer

```<code>#include <stdio.h>
#include <string.h>

int main ()
{
  char str[] ="blahblah<mailto:agent007@example.org>blahblahblah";
  char * tch;
  char * saved;                     /* pmg */
  tch = strtok (str,"<:@");
  while (tch != NULL)
  {
    int savenext = 0;               /* pmg */
    if (!strcmp(tch, "mailto"))     /* pmg, UNTESTED CODE, need to check case? */
    {                               /* pmg */
      savenext = 1;                 /* pmg */
    }                               /* pmg */
    printf ("%s\n",tch);
    tch = strtok (NULL, "<:@");
    if (savenext == 1)              /* pmg, UNTESTED CODE */
    {                               /* pmg */
      saved = tch;                  /* pmg */
    }                               /* pmg */
  }
  printf ("saved: %s\n", saved);    /* pmg */
  return 0;
}
</code>```

Title: get substring from string in C

Body:
I am trying to write a program in C, which will allow me to get a string I want between two other strings that will be defined. To be more specific, my example string is

 "blahblah<mailto:agent007@example.org>blahblahblah"

and I need to be able to extract the "agent007" substring to a new variable. I have tried the strtok() method, but the thing is I can't extract the tokens to a new variable or an array. I have tokenized the string and the statement that would suite me fine would be something like " if token[i] == "mailto" && token[i+2] == "example" then mailAdd = token[i+1] " (in a pseudo-code way :) )

my program so far

#include <stdio.h>
#include <string.h>

int main ()
{
  char str[] ="blahblah<mailto:agent007@example.org>blahblahblah";
  char * tch;
  tch = strtok (str,"<:@");
  while (tch != NULL)
  {
    printf ("%s\n",tch);
    tch = strtok (NULL, "<:@");
  }
  return 0;
}

Of course, any other suggestion beyond tokens will be greatly appreciated -

Body:
My first thought was to use strstr for "mailto:" and strchr for the '@'

// pseudo code
char *mailto = strstr(src, "mailto:"); // possibly convert src to lowercase
char *atsign = strchr(mailto, '@');
while (mailto < atsign) *dst++ = *mailto++;

Of course that is a very rough draft. It needs lots of refining (failure to find the "mailto:" string or '@' char, error-checking, special cases, tests, ...)

Saving the strtok pointer

#include <stdio.h>
#include <string.h>

int main ()
{
  char str[] ="blahblah<mailto:agent007@example.org>blahblahblah";
  char * tch;
  char * saved;                     /* pmg */
  tch = strtok (str,"<:@");
  while (tch != NULL)
  {
    int savenext = 0;               /* pmg */
    if (!strcmp(tch, "mailto"))     /* pmg, UNTESTED CODE, need to check case? */
    {                               /* pmg */
      savenext = 1;                 /* pmg */
    }                               /* pmg */
    printf ("%s\n",tch);
    tch = strtok (NULL, "<:@");
    if (savenext == 1)              /* pmg, UNTESTED CODE */
    {                               /* pmg */
      saved = tch;                  /* pmg */
    }                               /* pmg */
  }
  printf ("saved: %s\n", saved);    /* pmg */
  return 0;
}


问:
send token to server Swift 3
i'm trying to send a token to my server to check if token is still valid or has expired. the token value is pulled from saved data on the device. But no matter what i try it keeps giving me "missing token" which is the status message for when i've sent empty string.

```<code>    // load content in user var
    user = UserDefaults.standard.value(forKey: "parseJSON") as? NSDictionary

    // if user is once logged in / register, keep him logged in
    if user != nil {
        print(user as Any)

        let userToken = user!["token"] as? String

        let url = NSURL(string: "http://fmm.dummy.com/api/v1/auth/me")!

        var request = URLRequest(url: url as URL)

        request.setValue("Bearer \(String(describing: userToken))", forHTTPHeaderField: "Authorization")

        request.httpMethod = "POST"
</code>```

When i edited and did this, the error message change to "invalid token" which meant i was sending something. it just wasn't correct

```<code>    // load content in user var
    user = UserDefaults.standard.value(forKey: "parseJSON") as? NSDictionary

    // if user is once logged in / register, keep him logged in
    if user != nil {
        print(user as Any)

        let userToken = user!["token"] as? String

        let a: Character = "<"
        let b: Character = ">"
        let url = NSURL(string: "http://fmm.dummy.com/api/v1/auth/me")!

        var request = URLRequest(url: url as URL)

        request.setValue("Bearer .append\(a)\(String(describing: userToken)).append\(b)", forHTTPHeaderField: "Authorization")

        request.httpMethod = "POST"

        //launch session
        URLSession.shared.dataTask(with: request) { data, response, error in
</code>```

can someone please help me figure out what am doing wrong?
thanks

///EDIT
Hi when i edited as you had suggested and came up with this, i couldn't even print to console. Here is the full code for your consideration. Thanks for the response.
if let user = UserDefaults.standard.object(forKey: "parseJSON") as? [String:Any],
           let userToken = user["token"] as? String {

```<code>       let url = URL(string: "http://fmm.dummy.com/api/v1/auth/me")!
       var request = URLRequest(url: url)

       let tokenString = "Bearer " + userToken
       request.setValue(tokenString, forHTTPHeaderField: "Authorization")
       request.httpMethod = "POST"

       //launch session
       URLSession.shared.dataTask(with: request) { data, response, error in

           //check if no error
           if error == nil{

               do {

                   let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary

                   guard let parseJSON = json else{

                       print ("Error While Parsing")
                       return
                   }
                   print(parseJSON)

                   let statusMsg = parseJSON["status"] as? String

                   if  statusMsg == "OK"{
                       //token still valid
                       self.login()

                   }else {
                       //token is invalid
                       // get main queue to communicate back to user
                       DispatchQueue.main.async(execute: {
                           let message = parseJSON["status_msg"] as! String
                           appDelegate.infoView(message: message, color: colorSmoothRed)
                       })
                   }

               }catch{
                   // get main queue to communicate back to user
                   DispatchQueue.main.async(execute: {
                       let message = "\(error)"
                       appDelegate.infoView(message: message, color: colorSmoothRed)
                   })
                   return

               }

           }else{

               // get main queue to communicate back to user
               DispatchQueue.main.async(execute: {
                   let message = error!.localizedDescription
                   appDelegate.infoView(message: message, color: colorSmoothRed)
               })
               return
           }
           }.resume()

   }
</code>```

I'm trying to write code in appdelegate.swift that checks if the token saved from a previous login is still valid or has expired! the saved object on the user device is as follows. When i print user to the console i get this. ::--

Optional({
    response =     {
        token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjIsImlzcyI6Imh0dHA6XC9cL3htbS54bW9iaWxlbW9uZXkuY29tXC9hcGlcL3YxXC9hdXRoIiwiaWF0IjoxNDk2ODUyNTkxLCJleHAiOjE0OTY4NTYxOTEsIm5iZiI6MTQ5Njg1MjU5MSwianRpIjoiOTFhYjE0MjZkMGZmN2RjZDVjOTQzNTlkZGY4OGY0ZmYifQ.WaQFprfRbJMDQ72IORtWrcSmUqY3EaJp5BAqjijvUAc";
        verified = 1;
    };
    status = OK;
})

答:
You are using too many optionals which can cause unexpected literal "Optional(<value>)" when calling the description method.

Unwrap all optionals safely with optional bindings:

```<code>if let user = UserDefaults.standard.object(forKey: "parseJSON") as? [String:Any],
    let userToken = user["token"] as? String {

    let url = URL(string: "http://fmm.dummy.com/api/v1/auth/me")!
    var request = URLRequest(url: url)

    let tokenString = "Bearer " + userToken
    request.setValue(tokenString, forHTTPHeaderField: "Authorization")
    request.httpMethod = "POST"
    ...
</code>```

As always, never use valueForKey to get a single object from UserDefaults, use always objectForKey, and never use NSDictionary for a property list compliant dictionary, use always [String:Any].

Title: send token to server Swift 3

Body:
i'm trying to send a token to my server to check if token is still valid or has expired. the token value is pulled from saved data on the device. But no matter what i try it keeps giving me "missing token" which is the status message for when i've sent empty string.

    // load content in user var
    user = UserDefaults.standard.value(forKey: "parseJSON") as? NSDictionary

    // if user is once logged in / register, keep him logged in
    if user != nil {
        print(user as Any)

        let userToken = user!["token"] as? String

        let url = NSURL(string: "http://fmm.dummy.com/api/v1/auth/me")!

        var request = URLRequest(url: url as URL)

        request.setValue("Bearer \(String(describing: userToken))", forHTTPHeaderField: "Authorization")

        request.httpMethod = "POST"

When i edited and did this, the error message change to "invalid token" which meant i was sending something. it just wasn't correct

    // load content in user var
    user = UserDefaults.standard.value(forKey: "parseJSON") as? NSDictionary

    // if user is once logged in / register, keep him logged in
    if user != nil {
        print(user as Any)

        let userToken = user!["token"] as? String

        let a: Character = "<"
        let b: Character = ">"
        let url = NSURL(string: "http://fmm.dummy.com/api/v1/auth/me")!

        var request = URLRequest(url: url as URL)

        request.setValue("Bearer .append\(a)\(String(describing: userToken)).append\(b)", forHTTPHeaderField: "Authorization")

        request.httpMethod = "POST"

        //launch session
        URLSession.shared.dataTask(with: request) { data, response, error in

can someone please help me figure out what am doing wrong?
thanks

///EDIT
Hi when i edited as you had suggested and came up with this, i couldn't even print to console. Here is the full code for your consideration. Thanks for the response.
if let user = UserDefaults.standard.object(forKey: "parseJSON") as? [String:Any],
           let userToken = user["token"] as? String {

       let url = URL(string: "http://fmm.dummy.com/api/v1/auth/me")!
       var request = URLRequest(url: url)

       let tokenString = "Bearer " + userToken
       request.setValue(tokenString, forHTTPHeaderField: "Authorization")
       request.httpMethod = "POST"

       //launch session
       URLSession.shared.dataTask(with: request) { data, response, error in

           //check if no error
           if error == nil{

               do {

                   let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary

                   guard let parseJSON = json else{

                       print ("Error While Parsing")
                       return
                   }
                   print(parseJSON)

                   let statusMsg = parseJSON["status"] as? String

                   if  statusMsg == "OK"{
                       //token still valid
                       self.login()

                   }else {
                       //token is invalid
                       // get main queue to communicate back to user
                       DispatchQueue.main.async(execute: {
                           let message = parseJSON["status_msg"] as! String
                           appDelegate.infoView(message: message, color: colorSmoothRed)
                       })
                   }

               }catch{
                   // get main queue to communicate back to user
                   DispatchQueue.main.async(execute: {
                       let message = "\(error)"
                       appDelegate.infoView(message: message, color: colorSmoothRed)
                   })
                   return

               }

           }else{

               // get main queue to communicate back to user
               DispatchQueue.main.async(execute: {
                   let message = error!.localizedDescription
                   appDelegate.infoView(message: message, color: colorSmoothRed)
               })
               return
           }
           }.resume()

   }

I'm trying to write code in appdelegate.swift that checks if the token saved from a previous login is still valid or has expired! the saved object on the user device is as follows. When i print user to the console i get this. ::--

Optional({
    response =     {
        token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjIsImlzcyI6Imh0dHA6XC9cL3htbS54bW9iaWxlbW9uZXkuY29tXC9hcGlcL3YxXC9hdXRoIiwiaWF0IjoxNDk2ODUyNTkxLCJleHAiOjE0OTY4NTYxOTEsIm5iZiI6MTQ5Njg1MjU5MSwianRpIjoiOTFhYjE0MjZkMGZmN2RjZDVjOTQzNTlkZGY4OGY0ZmYifQ.WaQFprfRbJMDQ72IORtWrcSmUqY3EaJp5BAqjijvUAc";
        verified = 1;
    };
    status = OK;
})

Body:
You are using too many optionals which can cause unexpected literal "Optional(<value>)" when calling the description method.

Unwrap all optionals safely with optional bindings:

if let user = UserDefaults.standard.object(forKey: "parseJSON") as? [String:Any],
    let userToken = user["token"] as? String {

    let url = URL(string: "http://fmm.dummy.com/api/v1/auth/me")!
    var request = URLRequest(url: url)

    let tokenString = "Bearer " + userToken
    request.setValue(tokenString, forHTTPHeaderField: "Authorization")
    request.httpMethod = "POST"
    ...

As always, never use valueForKey to get a single object from UserDefaults, use always objectForKey, and never use NSDictionary for a property list compliant dictionary, use always [String:Any].


问:
Key Frame Extraction From Video
I need Need To extract Key Frames from Video/Stream.So is there any standard implementation.
I am using open CV.
(Currently i am extracting frames each second which is slower i need to improve performance.)
So if any one has optimized implementation please reply in here.

答:
You can use ffprobe to extract key frames. It is a tool in ffmpeg.

Use the command:

```<code>ffprobe in.mp4 -select_streams v -show_entries frame=key_frame,pkt_pts_time -of csv=nk=1:p=0 | findstr "1,"
</code>```

Title: Key Frame Extraction From Video

Body:
You can use ffprobe to extract key frames. It is a tool in ffmpeg.

Use the command:

ffprobe in.mp4 -select_streams v -show_entries frame=key_frame,pkt_pts_time -of csv=nk=1:p=0 | findstr "1,"


问:
Semantic-UI-React could not enable debug
I am using semantic-ui-react and I am trying to create snapshot tests using jest. However, I keep getting this message. Could someone shed some light on this? I am using semantic with nextjs.</p>

```<code>console.error node_modules/fbjs/lib/warning.js:36
      Warning: ReactTestUtils has been moved to react-dom/test-utils. Update references to remove this warning.
    console.error node_modules/semantic-ui-react/dist/commonjs/lib/debug.js:30
      Semantic-UI-React could not enable debug.
    console.error node_modules/semantic-ui-react/dist/commonjs/lib/debug.js:31
      TypeError: Cannot read property 'debug' of undefined
</code>```

答:
Are you on Windows? If so, how do you execute the tests? I was facing the same issue earlier and was able to resolve it.

I had the following in my package.json:

```<code>"run_test" : "set NODE_ENV=test && npm run test",
"test": "./node_modules/.bin/mocha --compilers js:babel-core/register --recursive",
</code>```

The problem with this, however, is that windows will set your NODE_ENV as "test " and not as "test", notice the trailing whitespace. The solution for me was to fix write the scripts by removing the whitespace:

```<code>"run_test" : "set NODE_ENV=test&&npm run test",
"test": "./node_modules/.bin/mocha --compilers js:babel-core/register --recursive",
</code>```

Body:
I am using semantic-ui-react and I am trying to create snapshot tests using jest. However, I keep getting this message. Could someone shed some light on this? I am using semantic with nextjs.

console.error node_modules/fbjs/lib/warning.js:36
      Warning: ReactTestUtils has been moved to react-dom/test-utils. Update references to remove this warning.
    console.error node_modules/semantic-ui-react/dist/commonjs/lib/debug.js:30
      Semantic-UI-React could not enable debug.
    console.error node_modules/semantic-ui-react/dist/commonjs/lib/debug.js:31
      TypeError: Cannot read property 'debug' of undefined

Body:
Are you on Windows? If so, how do you execute the tests? I was facing the same issue earlier and was able to resolve it.

I had the following in my package.json:

"run_test" : "set NODE_ENV=test && npm run test",
"test": "./node_modules/.bin/mocha --compilers js:babel-core/register --recursive",

The problem with this, however, is that windows will set your NODE_ENV as "test " and not as "test", notice the trailing whitespace. The solution for me was to fix write the scripts by removing the whitespace:

"run_test" : "set NODE_ENV=test&&npm run test",
"test": "./node_modules/.bin/mocha --compilers js:babel-core/register --recursive",


问:
cuda kernel for conway's game of life
I'm trying to calculate the number of transitions that would be made in a run of Conway's GOL for a pxq matrix for n iterations. For instance, given 1 iteration with the initial state being 1 blinker (as below). there would be 5 transitions (2 births, 1 survival, 2 deaths from underpopulation). I've already got this working, but I'd like to convert this logic to run using CUDA. Below is what I want to port to CUDA.

    code:

```<code>    static void gol() // call this iterations x's
    {
        int[] tempGrid = new int[rows * cols]; // grid holds init conditions
        for (int i = 0; i < rows; i++)
        {
            for (int j = 0; j < cols; j++)
            {
                tempGrid[i * cols + j] = grid[i * cols + j];
            }
        }

        for (int i = 0; i < rows; i++)
        {
            for (int j = 0; j < cols; j++)
            {
                int numNeighbors = neighbors(i, j); // finds # of neighbors

                if (grid[i * cols + j] == 1 && numNeighbors > 3)
                {
                    tempGrid[i * cols + j] = 0;
                    overcrowding++;
                }
                else if (grid[i * cols + j] == 1 && numNeighbors < 2)
                {
                    tempGrid[i * cols + j] = 0;
                    underpopulation++;
                }
                else if (grid[i * cols + j] == 1 && numNeighbors > 1)
                {
                    tempGrid[i * cols + j] = 1;
                    survival++;
                }
                else if (grid[i * cols + j] == 0 && numNeighbors == 3)
                {
                    tempGrid[i * cols + j] = 1;
                    birth++;
                }
            }
        }

        grid = tempGrid;
    }
</code>```

答:
Your main slowdown is going to be main memory access. So I'd suggest that you pick a largish thread block size based on the hardware you have available. 256 (16x16) is a good choice for cross-hardware compatibility. Each of those thread blocks is going to calculate the results for a slightly smaller section of the board -- if you used 16x16, they'll calculate the results for a 14x14 section of the board, since there is a one element border. (The reason to use a 16x16 block to calculate a 14x14 chunk rather than a 16x16 chunk is for memory read coalescing.)

Divide the board up into (say) 14x14 chunks; that is your grid (organized however you see fit, but most likely something like board_width / 14, board_height / 14.

Within the kernels, have each thread load its element into shared memory. Then syncthreads. Then have the middle 14x14 elements calculate the new value (using the values stored in shared memory) and write it back into global memory. The use of shared memory helps minimize global reads and writes. This is also the reason to have your thread block size as big as possible -- the edges and corners are "wasted" global memory accesses, since the values fetched there only get used 1 or 3 times, not 9 times.

Title: cuda kernel for conway's game of life

Body:
I'm trying to calculate the number of transitions that would be made in a run of Conway's GOL for a pxq matrix for n iterations. For instance, given 1 iteration with the initial state being 1 blinker (as below). there would be 5 transitions (2 births, 1 survival, 2 deaths from underpopulation). I've already got this working, but I'd like to convert this logic to run using CUDA. Below is what I want to port to CUDA.

    code:

    static void gol() // call this iterations x's
    {
        int[] tempGrid = new int[rows * cols]; // grid holds init conditions
        for (int i = 0; i < rows; i++)
        {
            for (int j = 0; j < cols; j++)
            {
                tempGrid[i * cols + j] = grid[i * cols + j];
            }
        }

        for (int i = 0; i < rows; i++)
        {
            for (int j = 0; j < cols; j++)
            {
                int numNeighbors = neighbors(i, j); // finds # of neighbors

                if (grid[i * cols + j] == 1 && numNeighbors > 3)
                {
                    tempGrid[i * cols + j] = 0;
                    overcrowding++;
                }
                else if (grid[i * cols + j] == 1 && numNeighbors < 2)
                {
                    tempGrid[i * cols + j] = 0;
                    underpopulation++;
                }
                else if (grid[i * cols + j] == 1 && numNeighbors > 1)
                {
                    tempGrid[i * cols + j] = 1;
                    survival++;
                }
                else if (grid[i * cols + j] == 0 && numNeighbors == 3)
                {
                    tempGrid[i * cols + j] = 1;
                    birth++;
                }
            }
        }

        grid = tempGrid;
    }


问:
OpenGL 3.3 vertex buffer deletion before frame finished
This is an advanced OpenGL question and tbh. it seems more like a driver bug. I know that the standard explicitly states, that deletion of an object only deletes it's name, therefore a generator function can return the same name. However it's not clear on how to deal with this...

The situation is the following: I have a so called "transient" (C++) object (TO from now on), which generates GL objects, enqueues commands using them, then deletes them.

Now consider that I use more than one of this kind before I call SwapBuffers(). The following happens:

TO 1. generates a vertex buffer named VBO1, along with a VAO1 and other things

TO 1. calls some mapping/drawing commands with VBO1

TO 1. deletes the VAO1 and VBO1 (therefore the name VBO1 is freed)

TO 2. generates a vertex buffer object, now of course with the same name (VBO1) as the name 1 is deleted and available, along with another VAO (probably 1)

TO 2. calls some other mapping/drawing commands with this new VBO1 (different vertex positions, etc.)

TO 2. deletes the new VBO1

SwapBuffers()

And the result is: only the modifications performed by TO 1. are in effect. In a nutshell: I wanted to render a triangle, then a square, but I only got the triangle.

Workaround: not deleting the VBO, so I get a new name in TO 2. (VBO2)

I would like to ask for your help in this matter; although I'm aware of the fact that I shouldn't delete/generate objects mid-frame, but aside that, this "buggy" mechanism really disturbs me (I mean how can I trust GL then?...short answer: I can't...)

(sideonote: I've been programming 3D graphics since 12 years, but this thing really gave me the creeps...)

答:
I found the cause of the problem, I think it's worth mentioning (so that other developers won't fall into the same hole). The actual problem is the VAO, or more precisely the caching of the VAO.

In Metal and Vulkan the input layout is completely independent of the actual buffers used: you only specify the binding point (location) where the buffer is going to be.

But not in OpenGL... the VAO actually holds a strong reference to the vertex buffer which was bound during it's creation. Therefore the following thing happened:

VBO1 was created, VAO1 was created

VAO1 was cached in the pipeline cache

VBO1 was deleted, but only the name was freed, not the object

glGenBuffers() returns 1 again as the name is available

but VAO1 in the cache still references the old VBO1

the driver gets confused and doesn't let me modify the new VBO1

And the solution...well... For now when a vertex buffer gets deleted I delete any cached pipelines that reference that buffer.

On the long term tho: I'm going to maintain a separate cache for input layouts (even if it's part of the pipeline state), and move the transient object further up, so that it becomes less transient.

Welcome to the world of OpenGL...


问:
laravel like query is not working?
This is my code :

```<code> $lists = DB::table('connection_request as cr')
                    ->leftJoin('users as u', function($join)
                         {
                             $join->on('u.id', '=', 'cr.sender_id')->orOn('u.id','=', 'cr.receiver_id');
                         })
                    ->select('cr.id as connection_id','cr.sender_id as sen_id','cr.receiver_id as rec_id','cr.approve_status','u.id','u.user_type','u.user_type_id',DB::raw("IF(u.avatar = '', 'uploads/avatar/default.jpg', u.avatar) as avatar"),'u.name','u.email')
                    ->where(function($query) use ($user_id)
                        {
                        if(!empty($user_id)):
                            $query->Where('cr.receiver_id','=', $user_id);
                        endif;
                        if(!empty($user_id)):
                            $query->orWhere('cr.sender_id','=', $user_id);
                        endif;
                     })
                    ->where(function($query) use ($searchValue)
                        {
                        if(!empty($searchValue)):
                           $query->Where('u.name','like', '%' . $searchValue . '%');
                           $query->orWhere('u.email','like', '%' . $searchValue . '%');
                        endif;
                     })
                    ->where('cr.approve_status','=',1)
                    ->where('u.id','!=',$user_id)
                    ->get();
</code>```

and it provide mysql query like this

```<code>select `cr`.`id` as `connection_id`, `cr`.`sender_id` as `sen_id`, `cr`.`receiver_id` as `rec_id`, `cr`.`approve_status`, `u`.`id`, `u`.`user_type`, `u`.`user_type_id`, IF(u.avatar = '', 'uploads/avatar/default.jpg', u.avatar) as avatar, `u`.`name`, `u`.`email` from `connection_request` as `cr` left join `users` as `u` on `u`.`id` = `cr`.`sender_id` or `u`.`id` = `cr`.`receiver_id` where (`cr`.`receiver_id` = 10 or `cr`.`sender_id` = 10) and (`u`.`name` LIKE 'pri' or `u`.`email` LIKE 'pri') and `cr`.`approve_status` = 1 and `u`.`id` != 10
</code>```

So, I can't able to get result because after like it should have % symbol but, generate laravel query not having percentage symbol

my below raw query is working perfect

```<code>select `cr`.`id` as `connection_id`, `cr`.`sender_id` as `sen_id`, `cr`.`receiver_id` as `rec_id`, `cr`.`approve_status`, `u`.`id`, `u`.`user_type`, `u`.`user_type_id`, IF(u.avatar = '', 'uploads/avatar/default.jpg', u.avatar) as avatar, `u`.`name`, `u`.`email` from `connection_request` as `cr` left join `users` as `u` on `u`.`id` = `cr`.`sender_id` or `u`.`id` = `cr`.`receiver_id` where (`cr`.`receiver_id` = 10 or `cr`.`sender_id` = 10) and (`u`.`name` LIKE '%pri%' or `u`.`email` LIKE '%pri%') and `cr`.`approve_status` = 1 and `u`.`id` != 10
</code>```

Please check and help me guys,

Thanks

答:
Your where condition can also be like this ..
It will work..</p>

```<code>->where(function($query) use ($searchValue)
                       {
                       if(!empty($searchValue)):
                       $query->Where('u.name','like', DB::raw("'%$searchValue%'"));
                       $query->orWhere('u.email','like', DB::raw("'%$searchValue%'"));
                       endif;
                    })
</code>```

Title: laravel like query is not working?

Body:
This is my code :

 $lists = DB::table('connection_request as cr')
                    ->leftJoin('users as u', function($join)
                         {
                             $join->on('u.id', '=', 'cr.sender_id')->orOn('u.id','=', 'cr.receiver_id');
                         })
                    ->select('cr.id as connection_id','cr.sender_id as sen_id','cr.receiver_id as rec_id','cr.approve_status','u.id','u.user_type','u.user_type_id',DB::raw("IF(u.avatar = '', 'uploads/avatar/default.jpg', u.avatar) as avatar"),'u.name','u.email')
                    ->where(function($query) use ($user_id)
                        {
                        if(!empty($user_id)):
                            $query->Where('cr.receiver_id','=', $user_id);
                        endif;
                        if(!empty($user_id)):
                            $query->orWhere('cr.sender_id','=', $user_id);
                        endif;
                     })
                    ->where(function($query) use ($searchValue)
                        {
                        if(!empty($searchValue)):
                           $query->Where('u.name','like', '%' . $searchValue . '%');
                           $query->orWhere('u.email','like', '%' . $searchValue . '%');
                        endif;
                     })
                    ->where('cr.approve_status','=',1)
                    ->where('u.id','!=',$user_id)
                    ->get();

and it provide mysql query like this

select `cr`.`id` as `connection_id`, `cr`.`sender_id` as `sen_id`, `cr`.`receiver_id` as `rec_id`, `cr`.`approve_status`, `u`.`id`, `u`.`user_type`, `u`.`user_type_id`, IF(u.avatar = '', 'uploads/avatar/default.jpg', u.avatar) as avatar, `u`.`name`, `u`.`email` from `connection_request` as `cr` left join `users` as `u` on `u`.`id` = `cr`.`sender_id` or `u`.`id` = `cr`.`receiver_id` where (`cr`.`receiver_id` = 10 or `cr`.`sender_id` = 10) and (`u`.`name` LIKE 'pri' or `u`.`email` LIKE 'pri') and `cr`.`approve_status` = 1 and `u`.`id` != 10

So, I can't able to get result because after like it should have % symbol but, generate laravel query not having percentage symbol

my below raw query is working perfect

select `cr`.`id` as `connection_id`, `cr`.`sender_id` as `sen_id`, `cr`.`receiver_id` as `rec_id`, `cr`.`approve_status`, `u`.`id`, `u`.`user_type`, `u`.`user_type_id`, IF(u.avatar = '', 'uploads/avatar/default.jpg', u.avatar) as avatar, `u`.`name`, `u`.`email` from `connection_request` as `cr` left join `users` as `u` on `u`.`id` = `cr`.`sender_id` or `u`.`id` = `cr`.`receiver_id` where (`cr`.`receiver_id` = 10 or `cr`.`sender_id` = 10) and (`u`.`name` LIKE '%pri%' or `u`.`email` LIKE '%pri%') and `cr`.`approve_status` = 1 and `u`.`id` != 10

Please check and help me guys,

Thanks

Body:
Your where condition can also be like this ..
It will work..

->where(function($query) use ($searchValue)
                       {
                       if(!empty($searchValue)):
                       $query->Where('u.name','like', DB::raw("'%$searchValue%'"));
                       $query->orWhere('u.email','like', DB::raw("'%$searchValue%'"));
                       endif;
                    })


问:
autocomplete ='off' is not working when the input type is password and make the input field above it to enable autocomplete
I have an form with autocomplete disabled but it does not works and makes the autocomplete to be enabled in firefox and higher version of chrome

```<code><form method="post" autocomplete="off" action="">
    <ul class="field-set">
    <li>
        <label>Username:</label>
        <input type="text" name="acct" id="username" maxlength="100" size="20">
    </li>
    <li>
        <label>Password:</label>
        <input type="password" name="pswd" id="password" maxlength="16" size="20" >
    </li>
    <li>
        <input type="submit" class="button" value="Login" id="Login" name="Login">
    </li>
    </ul>
</form>
</code>```

When the type is changed from password to text it works in all browser.
Can anyone help to solve this issue?

答:
For password , its not working currently.

So by default make password field as text and use following js code .

$('#real-password').on('input', function(){
            if ($(this).val() !== '') {
                $(this).attr('type', 'password');
            } else {
                $(this).attr('type', 'text');
            }
   });```

Body:
I have an form with autocomplete disabled but it does not works and makes the autocomplete to be enabled in firefox and higher version of chrome

<form method="post" autocomplete="off" action="">

        Username:
        <input type="text" name="acct" id="username" maxlength="100" size="20">

        Password:
        <input type="password" name="pswd" id="password" maxlength="16" size="20" >

        <input type="submit" class="button" value="Login" id="Login" name="Login">

</form>

When the type is changed from password to text it works in all browser.
Can anyone help to solve this issue?


问:
Unexpected server error in Google App Engine
I have a PHP application running on Google App Engine that uses Google Cloud SQL.

Recently we have seen an an increase in our user count and since then we have been getting the following error.

This happens frequently but in random views. We are sure there is nothing wrong with the code. This error however disappears once the user refreshes the browser.

Can someone help us to understand why this is happening?

答:
Krish, I am not sure what your setup is with replication etc, however if this issue started after an increase in users it is likely that you are reaching concurrent connection, queue limit issues.

The documentation for Cloud SQL https://cloud.google.com/sql/docs/mysql/diagnose-issues

Has a section on CloudSQL Instance limits. It is possible you are reaching the queue limit. This could be caused by way too many users making requests at the same time, or maybe you have a query that is too slow and clogs up the queue, causing users to overflow the queue.

That same page in the documentation talks about enabling query logs (way down the page) and shows you how once activated you can query your SQL logs for slow queries that could be causing issues.

```<code>SELECT * FROM mysql.slow_log;
</code>```

If you are able to solve it by fixing your queries then great! If not, maybe it is time to introduce read replicas to spread the load between a couple of instances of your DB.

Body:
Krish, I am not sure what your setup is with replication etc, however if this issue started after an increase in users it is likely that you are reaching concurrent connection, queue limit issues.

The documentation for Cloud SQL https://cloud.google.com/sql/docs/mysql/diagnose-issues

Has a section on CloudSQL Instance limits. It is possible you are reaching the queue limit. This could be caused by way too many users making requests at the same time, or maybe you have a query that is too slow and clogs up the queue, causing users to overflow the queue.

That same page in the documentation talks about enabling query logs (way down the page) and shows you how once activated you can query your SQL logs for slow queries that could be causing issues.

SELECT * FROM mysql.slow_log;

If you are able to solve it by fixing your queries then great! If not, maybe it is time to introduce read replicas to spread the load between a couple of instances of your DB.


问:
Simple TYPO3 Fluid fileupload with Ajax?
Currently I am stuck in finding a nice, compatible way to realize an Ajax-File-Upload in TYPO3 Fluid. I am aware of the Demo-Extension by Helmut Hummel on GitHub, but this is, as I see it, rather overkill for my needs and does not include "real" ajax submit. I absolutely DON`T want to have any page reload on that specific site.
I want to build an ajax-upload of a csv-file, which gets analyzed by my own controller-action, the results shall be presented in a lightbox afterwards (confirmation step).
Is there any elegant way to pass the text-contents of a file to my own controller in TYPO3?</p>

答:
You can simply send the file data as binary using jquery ajax or any other javascript framework from Front-end.

Here is the javascript/jQuery to send a file as binary.

```<code>var file_data = $("#upload").prop("files")[0];
var form_data = new FormData();
form_data.append('tx_extname_plugin[file]', file_data);
$.ajax({
  url: 'your action url',
  dataType: 'json',
  cache: false,
  contentType: false,
  processData: false,
  data: form_data,
  type: 'post',
  success: function(data){

  }
});
</code>```

In Controller Action, you can upload the file from a controller as your desired position. After that, you can use the uploaded file for your further stuff.

```<code>public function demoAction(){
    $uploadedFile = $_FILE['file'];
}
</code>```

May be this code is old school because I had implemented it year ago.

Body:
You can simply send the file data as binary using jquery ajax or any other javascript framework from Front-end.

Here is the javascript/jQuery to send a file as binary.

var file_data = $("#upload").prop("files")[0];
var form_data = new FormData();
form_data.append('tx_extname_plugin[file]', file_data);
$.ajax({
  url: 'your action url',
  dataType: 'json',
  cache: false,
  contentType: false,
  processData: false,
  data: form_data,
  type: 'post',
  success: function(data){

  }
});

In Controller Action, you can upload the file from a controller as your desired position. After that, you can use the uploaded file for your further stuff.

public function demoAction(){
    $uploadedFile = $_FILE['file'];
}

May be this code is old school because I had implemented it year ago.


问:
How to make a CombinedChart have two different scales on MPAndroidChart?
I have a CombinedChart and I would like that LineChart will take left axis as reference and BarChart will take right axis as reference but I could not get it out.

I am trying the following code:

```<code>barDataSet.setAxisDependency(YAxis.AxisDependency.RIGHT);
lineDataSet.setAxisDependency(YAxis.AxisDependency.LEFT);
</code>```

but now both charts (LineChart and BarChart) are on the left (mixing them and right axis have disappeared).

Left and right axis have different granularity.

How can I properly make that each chart takes as reference one different Y axis (left or right respectively)?

Thanks in advance!

答:
This is certainly possible in MPAndroidChart version 3.0.2.

As you can observe from the screenshot below, the LineDataSet has AxisDependency.LEFT (scaled from 0 - 21) while the BarDataSet has AxisDependency.RIGHT (scaled from 0 - 50) and, as required, they have different granularity:

Here is a proof of concept for generating the above chart that is a simple adaptation of the example project on GitHub:

```<code>import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.view.WindowManager;

import com.github.mikephil.charting.charts.CombinedChart;
import com.github.mikephil.charting.charts.CombinedChart.DrawOrder;
import com.github.mikephil.charting.components.AxisBase;
import com.github.mikephil.charting.components.Legend;
import com.github.mikephil.charting.components.XAxis;
import com.github.mikephil.charting.components.XAxis.XAxisPosition;
import com.github.mikephil.charting.components.YAxis;
import com.github.mikephil.charting.data.BarData;
import com.github.mikephil.charting.data.BarDataSet;
import com.github.mikephil.charting.data.BarEntry;
import com.github.mikephil.charting.data.CombinedData;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;
import com.github.mikephil.charting.formatter.IAxisValueFormatter;

import java.util.ArrayList;

public class CombinedChartActivity extends FragmentActivity {

    private String[] mMonths = new String[] {
            "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec"
    };

    private CombinedChart mChart;
    private final int itemcount = 12;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_combined);

        mChart = (CombinedChart) findViewById(R.id.chart1);
        mChart.getDescription().setEnabled(false);
        mChart.setBackgroundColor(Color.WHITE);
        mChart.setDrawGridBackground(false);
        mChart.setDrawBarShadow(false);
        mChart.setHighlightFullBarEnabled(false);

        mChart.setDrawOrder(new DrawOrder[]{
                DrawOrder.BAR, DrawOrder.BUBBLE, DrawOrder.CANDLE, DrawOrder.LINE, DrawOrder.SCATTER
        });

        Legend l = mChart.getLegend();
        l.setWordWrapEnabled(true);
        l.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM);
        l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.CENTER);
        l.setOrientation(Legend.LegendOrientation.HORIZONTAL);
        l.setDrawInside(false);

        YAxis rightAxis = mChart.getAxisRight();
        rightAxis.setDrawGridLines(false);
        rightAxis.setGranularity(10f);
        rightAxis.setAxisMinimum(0f);

        YAxis leftAxis = mChart.getAxisLeft();
        leftAxis.setDrawGridLines(false);
        rightAxis.setGranularity(1f);
        leftAxis.setAxisMinimum(0f);

        XAxis xAxis = mChart.getXAxis();
        xAxis.setPosition(XAxisPosition.BOTH_SIDED);
        xAxis.setAxisMinimum(0f);
        xAxis.setGranularity(1f);
        xAxis.setValueFormatter(new IAxisValueFormatter() {
            @Override
            public String getFormattedValue(float value, AxisBase axis) {
                return mMonths[(int) value % mMonths.length];
            }
        });

        CombinedData data = new CombinedData();

        data.setData(generateLineData());
        data.setData(generateBarData());

        xAxis.setAxisMaximum(data.getXMax() + 0.25f);

        mChart.setData(data);
        mChart.invalidate();
    }

    private LineData generateLineData() {

        LineData d = new LineData();

        ArrayList<Entry> entries = new ArrayList<Entry>();

        for (int index = 0; index < itemcount; index++)
            entries.add(new Entry(index + 0.5f, getRandom(15, 5)));

        LineDataSet set = new LineDataSet(entries, "Line DataSet");
        set.setColor(Color.rgb(0,100,0));
        set.setLineWidth(2.5f);
        set.setCircleColor(Color.rgb(0,100,0));
        set.setCircleRadius(5f);
        set.setFillColor(Color.rgb(0,100,0));
        set.setMode(LineDataSet.Mode.CUBIC_BEZIER);
        set.setDrawValues(true);
        set.setValueTextSize(10f);
        set.setValueTextColor(Color.rgb(0,100,0));

        set.setAxisDependency(YAxis.AxisDependency.LEFT);
        d.addDataSet(set);

        return d;
    }

    private BarData generateBarData() {
        ArrayList<BarEntry> entries = new ArrayList<BarEntry>();

        for (int index = 0; index < itemcount; index++) {
            entries.add(new BarEntry(index, getRandom(25, 25)));
        }

        BarDataSet set = new BarDataSet(entries, "Bar DataSet");
        set.setColor(Color.rgb(60, 220, 78));
        set.setValueTextColor(Color.rgb(60, 220, 78));
        set.setValueTextSize(10f);
        set.setAxisDependency(YAxis.AxisDependency.RIGHT);

        return new BarData(set);
    }

    private float getRandom(float range, float startsfrom) {
        return (float) (Math.random() * range) + startsfrom;
    }
}
</code>```

Body:
I have a CombinedChart and I would like that LineChart will take left axis as reference and BarChart will take right axis as reference but I could not get it out.

I am trying the following code:

barDataSet.setAxisDependency(YAxis.AxisDependency.RIGHT);
lineDataSet.setAxisDependency(YAxis.AxisDependency.LEFT);

but now both charts (LineChart and BarChart) are on the left (mixing them and right axis have disappeared).

Left and right axis have different granularity.

How can I properly make that each chart takes as reference one different Y axis (left or right respectively)?

Thanks in advance!

Body:
This is certainly possible in MPAndroidChart version 3.0.2.

As you can observe from the screenshot below, the LineDataSet has AxisDependency.LEFT (scaled from 0 - 21) while the BarDataSet has AxisDependency.RIGHT (scaled from 0 - 50) and, as required, they have different granularity:

Here is a proof of concept for generating the above chart that is a simple adaptation of the example project on GitHub:

import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.view.WindowManager;

import com.github.mikephil.charting.charts.CombinedChart;
import com.github.mikephil.charting.charts.CombinedChart.DrawOrder;
import com.github.mikephil.charting.components.AxisBase;
import com.github.mikephil.charting.components.Legend;
import com.github.mikephil.charting.components.XAxis;
import com.github.mikephil.charting.components.XAxis.XAxisPosition;
import com.github.mikephil.charting.components.YAxis;
import com.github.mikephil.charting.data.BarData;
import com.github.mikephil.charting.data.BarDataSet;
import com.github.mikephil.charting.data.BarEntry;
import com.github.mikephil.charting.data.CombinedData;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;
import com.github.mikephil.charting.formatter.IAxisValueFormatter;

import java.util.ArrayList;

public class CombinedChartActivity extends FragmentActivity {

    private String[] mMonths = new String[] {
            "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec"
    };

    private CombinedChart mChart;
    private final int itemcount = 12;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_combined);

        mChart = (CombinedChart) findViewById(R.id.chart1);
        mChart.getDescription().setEnabled(false);
        mChart.setBackgroundColor(Color.WHITE);
        mChart.setDrawGridBackground(false);
        mChart.setDrawBarShadow(false);
        mChart.setHighlightFullBarEnabled(false);

        mChart.setDrawOrder(new DrawOrder[]{
                DrawOrder.BAR, DrawOrder.BUBBLE, DrawOrder.CANDLE, DrawOrder.LINE, DrawOrder.SCATTER
        });

        Legend l = mChart.getLegend();
        l.setWordWrapEnabled(true);
        l.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM);
        l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.CENTER);
        l.setOrientation(Legend.LegendOrientation.HORIZONTAL);
        l.setDrawInside(false);

        YAxis rightAxis = mChart.getAxisRight();
        rightAxis.setDrawGridLines(false);
        rightAxis.setGranularity(10f);
        rightAxis.setAxisMinimum(0f);

        YAxis leftAxis = mChart.getAxisLeft();
        leftAxis.setDrawGridLines(false);
        rightAxis.setGranularity(1f);
        leftAxis.setAxisMinimum(0f);

        XAxis xAxis = mChart.getXAxis();
        xAxis.setPosition(XAxisPosition.BOTH_SIDED);
        xAxis.setAxisMinimum(0f);
        xAxis.setGranularity(1f);
        xAxis.setValueFormatter(new IAxisValueFormatter() {
            @Override
            public String getFormattedValue(float value, AxisBase axis) {
                return mMonths[(int) value % mMonths.length];
            }
        });

        CombinedData data = new CombinedData();

        data.setData(generateLineData());
        data.setData(generateBarData());

        xAxis.setAxisMaximum(data.getXMax() + 0.25f);

        mChart.setData(data);
        mChart.invalidate();
    }

    private LineData generateLineData() {

        LineData d = new LineData();

        ArrayList<Entry> entries = new ArrayList<Entry>();

        for (int index = 0; index < itemcount; index++)
            entries.add(new Entry(index + 0.5f, getRandom(15, 5)));

        LineDataSet set = new LineDataSet(entries, "Line DataSet");
        set.setColor(Color.rgb(0,100,0));
        set.setLineWidth(2.5f);
        set.setCircleColor(Color.rgb(0,100,0));
        set.setCircleRadius(5f);
        set.setFillColor(Color.rgb(0,100,0));
        set.setMode(LineDataSet.Mode.CUBIC_BEZIER);
        set.setDrawValues(true);
        set.setValueTextSize(10f);
        set.setValueTextColor(Color.rgb(0,100,0));

        set.setAxisDependency(YAxis.AxisDependency.LEFT);
        d.addDataSet(set);

        return d;
    }

    private BarData generateBarData() {
        ArrayList<BarEntry> entries = new ArrayList<BarEntry>();

        for (int index = 0; index < itemcount; index++) {
            entries.add(new BarEntry(index, getRandom(25, 25)));
        }

        BarDataSet set = new BarDataSet(entries, "Bar DataSet");
        set.setColor(Color.rgb(60, 220, 78));
        set.setValueTextColor(Color.rgb(60, 220, 78));
        set.setValueTextSize(10f);
        set.setAxisDependency(YAxis.AxisDependency.RIGHT);

        return new BarData(set);
    }

    private float getRandom(float range, float startsfrom) {
        return (float) (Math.random() * range) + startsfrom;
    }
}