问:
Why is there a open bar below my images between the border/outline
I can't figure out why there is an open space between my image and the border/outline. I've set all of the borders, margins, and paddings to 0. I've even tried to take away any possible overflow, but it still remains. I looked to try to solve it using chrome's developer tools, but I had no success. I would love it if you guys could take a look and try to figure out what is happening. Let me know if you need any more information. Thanks.

var click = 0;
function checkClicks(imgs) {

 if(click == 0) {
    // Run your animation on first click
    document.getElementById('column1').classList.add('animate1')
    document.getElementById('column2').classList.add('animate2')
    document.getElementById('column3').classList.add('animate3')
 document.getElementById('column4').classList.add('animate4')
 document.getElementById('column5').classList.add('animate5')
 document.getElementById('column6').classList.add('animate6');
    // hold Images for 1s
  setTimeout(function(){
   myFunction(imgs);
  }, 2000);
 } else {
  myFunction(imgs);
 }

 click = 1;
}
function myFunction(imgs) {

 var expandImg = document.getElementById("expandedImg");
 expandImg.src = imgs.src;
 var imgParagraph = document.getElementById('img-paragraph');
 imgParagraph.innerHTML = imgs.getAttribute("head");

 expandImg.parentElement.style.display = "table-cell";
  imgParagraph.style.display = 'table-cell';

}```
<pre class="snippet-code-css lang-css prettyprint-override"><code>@font-face {
  font-family: 'futuralight';
  src: url('../Fonts/Futura Light/futura_light_regular-webfont.woff2') format('woff2'), url('../Fonts/Futura Light/futura_light_regular-webfont.woff') format('woff');
  font-weight: normal;
  font-style: normal;
}

@font-face {
  font-family: 'tekoregular';
  src: url('../Fonts/Teko/teko-regular-webfont.woff2') format('woff2'), url('../Fonts/Teko/teko-regular-webfont.woff') format('woff');
  font-weight: normal;
  font-style: normal;
}

@font-face {
  font-family: 'playfair_displayregular';
  src: url('../Fonts/Playfair Display/playfairdisplay-regular-webfont.woff2') format('woff2'), url('../Fonts/Playfair Display/playfairdisplay-regular-webfont.woff') format('woff');
  font-weight: normal;
  font-style: normal;
}

@font-face {
  font-family: 'poppinsmedium';
  src: url('../Fonts/Poppins/poppins-medium-webfont.woff2') format('woff2'), url('../Fonts/Poppins/poppins-medium-webfont.woff') format('woff');
  font-weight: normal;
  font-style: normal;
}

* {
  margin: 0px;
  padding: 0px;
  border: 0px;
}

.topnav {
  background-color: rgb(84, 104, 217);
  overflow: hidden;
  font-family: 'futuralight';
  font-weight: 900;
}

.topnav a {
  float: left;
  color: #f2f2f2;
  text-align: center;
  padding: 20px 21px;
  text-decoration: none;
  font-size: 19px;
  position: relative;
  left: 2%;
}

.topnav a:before {
  content: "";
  position: absolute;
  width: 84%;
  height: 2px;
  bottom: 6px;
  left: 8%;
  background-color: white;
  visibility: hidden;
  transform: scaleX(0);
  transition: all 0.3s ease-in-out 0s;
}

.topnav a:hover:before {
  visibility: visible;
  transform: scaleX(1);
}

.topnav a.active-menu:before {
  content: "";
  position: absolute;
  width: 84%;
  height: 2px;
  bottom: 6px;
  left: 8%;
  background-color: white;
  visibility: visible;
  transform: scaleX(1);
  transition: all 0.3s ease-in-out 0s;
}

.column {
  float: left;
  width: 25%;
}

/* Style the images inside the grid */

.column img {
  cursor: pointer;
  background-color:black;
}

.column img:hover {
  background-color:black;
  filter: brightness(70%);
}

#totalbody {
  background-color: #EEF0FC;
  height: 600px;
}

/* Clear floats after the columns */

.row:after {
  content: "";
  display: table;
  clear: both;
}

/* The expanding image container */

#expandedImg {
  position: absolute;
  width: 40%;
  top:160px;
  left:20px;
  border-radius:7px;
  box-shadow: 0 2.8px 2.2px rgba(0, 0, 0, 0.034), 0 6.7px 5.3px rgba(0, 0, 0, 0.048), 0 12.5px 10px rgba(0, 0, 0, 0.06), 0 22.3px 17.9px rgba(0, 0, 0, 0.072), 0 41.8px 33.4px rgba(0, 0, 0, 0.086), 0 100px 80px rgba(0, 0, 0, 0.12);
}

/* Expanding image text */

/* image paragraph */

#img-paragraph {
  display: none;
  vertical-align: top;
  text-align: left;
  position: absolute;
  height: 400px;
  width: 50%;
  background-color: white;
  box-shadow: 0 2.8px 2.2px rgba(0, 0, 0, 0.034), 0 6.7px 5.3px rgba(0, 0, 0, 0.048), 0 12.5px 10px rgba(0, 0, 0, 0.06), 0 22.3px 17.9px rgba(0, 0, 0, 0.072), 0 41.8px 33.4px rgba(0, 0, 0, 0.086), 0 100px 80px rgba(0, 0, 0, 0.12);
  border-radius: 7px;
  float: right;
  right: 30px;
  top: 120px;
}

#expanded-wrapper {
  width: 100%;
}

/* Closable button inside the expanded image */

.row {
  position: absolute;
  top: 80px;
}

.head1 {
  position: relative;
  left: 12px;
  top: 16px;
  color: rgb(84, 104, 217);
  font-weight: 900;
  font-size: 40px;
  font-family: 'futuralight';
  text-decoration: none;
  line-height: 1;
  padding-left:4%;
  padding-top:30px;
}

.head2 {
  position: relative;
  left: 12px;
  top: 16px;
  color: rgb(84, 104, 217);
  font-weight: 900;
  font-size: 40px;
  font-family: 'futuralight';
  text-decoration: none;
  line-height: 1;
  padding-left:4%;
  padding-top:30px;
}

.head3 {
  position: relative;
  left: 12px;
  top: 16px;
  color: rgb(84, 104, 217);
  font-weight: 900;
  font-size: 40px;
  font-family: 'futuralight';
  text-decoration: none;
  line-height: 1;
  padding-left:4%;
  padding-top:30px;
}
.head4 {
  position: relative;
  left: 12px;
  top: 16px;
  color: rgb(84, 104, 217);
  font-weight: 900;
  font-size: 40px;
  font-family: 'futuralight';
  text-decoration: none;
  line-height: 1;
  padding-left:4%;
  padding-top:30px;
}
.head5 {
  position: relative;
  left: 12px;
  top: 16px;
  color: rgb(84, 104, 217);
  font-weight: 900;
  font-size: 40px;
  font-family: 'futuralight';
  text-decoration: none;
  line-height: 1;
  padding-left:4%;
  padding-top:30px;
}
.head6 {
  position: relative;
  left: 12px;
  top: 16px;
  color: rgb(84, 104, 217);
  font-weight: 900;
  font-size: 40px;
  font-family: 'futuralight';
  text-decoration: none;
  line-height: 1;
  padding-left:4%;
  padding-top:30px;
}

.head1::before {
  content: '';
  background-color: rgb(84, 104, 217);
  width: 12px;
  height: 100%;
  position: absolute;
  right: 100%;
  bottom: -16px;
}
.head2::before {
  content: '';
  background-color: rgb(84, 104, 217);
  width: 12px;
  height: 100%;
  position: absolute;
  right: 100%;
  bottom: -16px;
}
.head3::before {
  content: '';
  background-color: rgb(84, 104, 217);
  width: 12px;
  height: 100%;
  position: absolute;
  right: 100%;
  bottom: -16px;
}
.head4::before {
  content: '';
  background-color: rgb(84, 104, 217);
  width: 12px;
  height: 100%;
  position: absolute;
  right: 100%;
  bottom: -16px;
}
.head5::before {
  content: '';
  background-color: rgb(84, 104, 217);
  width: 12px;
  height: 100%;
  position: absolute;
  right: 100%;
  bottom: -16px;
}
.head6::before {
  content: '';
  background-color: rgb(84, 104, 217);
  width: 12px;
  height: 100%;
  position: absolute;
  right: 100%;
  bottom: -16px;
}
.para1{
  width: 90%;
  position: relative;
  left: 6%;
  font-size: 17px;
  top: 60px;
  font-family: 'futuralight';
}
#column1 {
  position: absolute;
  width:250px;
  float:left;
  left:600px;
  top:30px;
  border: 0.5rem outset pink;
  outline: 0.5rem solid khaki;
}

.animate1 {
  -webkit-animation: animate1 2s normal ease-out;
  animation: animate1 2s forwards normal ease-out;
}

@-webkit-keyframes animate1 {
  0% {
      top:00px;
  }
  100% {
      position: absolute;
      top: 500px;
      left:50px;

  }
}
@keyframes animate1 {
  0% {
      top:00px;
  }
  100% {
      position: absolute;
      top: 500px;
      left:50px;
  }
}
#column2 {
  position: absolute;
  width:200px;
  float:left;
  left:300px;
  top:50px;
}

.animate2 {
  -webkit-animation: animate2 2s normal ease-out;
  animation: animate2 2s forwards normal ease-out;
}
@-webkit-keyframes animate2 {
  0% {
      top:00px;
  }
  100% {
    position: absolute;
    top: 500px;
    left:300px;
  }
}
@keyframes animate2 {
  0% {
      top:00px;
  }
  100% {
    position: absolute;
    top: 500px;
    left:300px;
  }
}
#column3 {
  position: absolute;
  width:200px;
  float:left;
  left:200px;
  top:80px;
}

.animate3 {
  -webkit-animation: animate3 2s normal ease-out;
  animation: animate3 2s forwards normal ease-out;
}
@-webkit-keyframes animate3 {
  0% {
      top:00px;
  }
  100% {
    position: absolute;
    top: 500px;
    left:500px;
  }
}
@keyframes animate3 {
  0% {
      top:00px;
  }
  100% {
    position: absolute;
    top: 500px;
    left:500px;
  }
}
#column4 {
  position: absolute;
  width:200px;
  float:left;
  left:300px;
  top:80px;
}

.animate4 {
  -webkit-animation: animate4 2s normal ease-out;
  animation: animate4 2s forwards normal ease-out;
}
@-webkit-keyframes animate4 {
  0% {
      top:00px;
  }
  100% {
    position: absolute;
    top: 500px;
    left:700px;
  }
}
@keyframes animate4 {
  0% {
      top:00px;
  }
  100% {
    position: absolute;
    top: 500px;
    left:700px;
  }
}
#column5 {
  position: absolute;
  width:200px;
  float:left;
  left:300px;
  top:80px;
  border: 0.5rem outset pink;
  outline: 0.5rem solid khaki;
}

.animate5 {
  -webkit-animation: animate5 2s normal ease-out;
  animation: animate5 2s forwards normal ease-out;
}
@-webkit-keyframes animate5 {
  0% {
    top:00px;
  }
  100% {
    position: absolute;
    top: 800px;
    left:700px;
    padding-bottom:500px;
  }
}
@keyframes animate5 {
  0% {
    top:00px;
  }
  100% {
    position: absolute;
    top: 800px;
    left:700px;
    margin-bottom:500px;
  }
}
#column6 {
  position: absolute;
  width:300px;
  float:left;
  left:600px;
  border: 0.5rem outset pink;
  outline: 0.5rem solid khaki;
  overflow:none;
}

.animate6 {
  -webkit-animation: animate6 2s normal ease-out;
  animation: animate6 2s forwards normal ease-out;
}
@-webkit-keyframes animate6 {
  0% {
      top:00px;
  }
  100% {
    position:absolute;
    top: 800px;
    left:50px;
  }
}
@keyframes animate6 {
  0% {
      top:00px;
  }
  100% {
    position:absolute;
    top: 800px;
    left:50px;
  }
}

@media only screen and (max-width: 830px) and (min-width: 760px) {
  .topnav {
    background-color: yellow;
    overflow: hidden;
  }
}

@media only screen and (max-width: 759px) and (min-width: 646px) {
  .topnav {
    background-color: red;
    overflow: hidden;
  }
}

@media only screen and (max-width: 645px) {
  .topnav {
    background-color: black;
    overflow: hidden;
  }
}</code>```

<!DOCTYPE html>

    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" type="text/css"  href="../CSS/styleprojects.css" />

    <title>Projects</title>

    Home
    Academics
    Projects
    Community Service

```

答:
It's because the image is an inline element and hence behaves like text. You can get rid of this effect by making the  tag use display: block or by setting font-size: 0 or line-height: 0 on the
.

Body:
I can't figure out why there is an open space between my image and the border/outline. I've set all of the borders, margins, and paddings to 0. I've even tried to take away any possible overflow, but it still remains. I looked to try to solve it using chrome's developer tools, but I had no success. I would love it if you guys could take a look and try to figure out what is happening. Let me know if you need any more information. Thanks.

var click = 0;
function checkClicks(imgs) {

 if(click == 0) {
    // Run your animation on first click
    document.getElementById('column1').classList.add('animate1')
    document.getElementById('column2').classList.add('animate2')
    document.getElementById('column3').classList.add('animate3')
 document.getElementById('column4').classList.add('animate4')
 document.getElementById('column5').classList.add('animate5')
 document.getElementById('column6').classList.add('animate6');
    // hold Images for 1s
  setTimeout(function(){
   myFunction(imgs);
  }, 2000);
 } else {
  myFunction(imgs);
 }

 click = 1;
}
function myFunction(imgs) {

 var expandImg = document.getElementById("expandedImg");
 expandImg.src = imgs.src;
 var imgParagraph = document.getElementById('img-paragraph');
 imgParagraph.innerHTML = imgs.getAttribute("head");

 expandImg.parentElement.style.display = "table-cell";
  imgParagraph.style.display = 'table-cell';

}

@font-face {
  font-family: 'futuralight';
  src: url('../Fonts/Futura Light/futura_light_regular-webfont.woff2') format('woff2'), url('../Fonts/Futura Light/futura_light_regular-webfont.woff') format('woff');
  font-weight: normal;
  font-style: normal;
}

@font-face {
  font-family: 'tekoregular';
  src: url('../Fonts/Teko/teko-regular-webfont.woff2') format('woff2'), url('../Fonts/Teko/teko-regular-webfont.woff') format('woff');
  font-weight: normal;
  font-style: normal;
}

@font-face {
  font-family: 'playfair_displayregular';
  src: url('../Fonts/Playfair Display/playfairdisplay-regular-webfont.woff2') format('woff2'), url('../Fonts/Playfair Display/playfairdisplay-regular-webfont.woff') format('woff');
  font-weight: normal;
  font-style: normal;
}

@font-face {
  font-family: 'poppinsmedium';
  src: url('../Fonts/Poppins/poppins-medium-webfont.woff2') format('woff2'), url('../Fonts/Poppins/poppins-medium-webfont.woff') format('woff');
  font-weight: normal;
  font-style: normal;
}

* {
  margin: 0px;
  padding: 0px;
  border: 0px;
}

.topnav {
  background-color: rgb(84, 104, 217);
  overflow: hidden;
  font-family: 'futuralight';
  font-weight: 900;
}

.topnav a {
  float: left;
  color: #f2f2f2;
  text-align: center;
  padding: 20px 21px;
  text-decoration: none;
  font-size: 19px;
  position: relative;
  left: 2%;
}

.topnav a:before {
  content: "";
  position: absolute;
  width: 84%;
  height: 2px;
  bottom: 6px;
  left: 8%;
  background-color: white;
  visibility: hidden;
  transform: scaleX(0);
  transition: all 0.3s ease-in-out 0s;
}

.topnav a:hover:before {
  visibility: visible;
  transform: scaleX(1);
}

.topnav a.active-menu:before {
  content: "";
  position: absolute;
  width: 84%;
  height: 2px;
  bottom: 6px;
  left: 8%;
  background-color: white;
  visibility: visible;
  transform: scaleX(1);
  transition: all 0.3s ease-in-out 0s;
}

.column {
  float: left;
  width: 25%;
}

/* Style the images inside the grid */

.column img {
  cursor: pointer;
  background-color:black;
}

.column img:hover {
  background-color:black;
  filter: brightness(70%);
}

#totalbody {
  background-color: #EEF0FC;
  height: 600px;
}

/* Clear floats after the columns */

.row:after {
  content: "";
  display: table;
  clear: both;
}

/* The expanding image container */

#expandedImg {
  position: absolute;
  width: 40%;
  top:160px;
  left:20px;
  border-radius:7px;
  box-shadow: 0 2.8px 2.2px rgba(0, 0, 0, 0.034), 0 6.7px 5.3px rgba(0, 0, 0, 0.048), 0 12.5px 10px rgba(0, 0, 0, 0.06), 0 22.3px 17.9px rgba(0, 0, 0, 0.072), 0 41.8px 33.4px rgba(0, 0, 0, 0.086), 0 100px 80px rgba(0, 0, 0, 0.12);
}

/* Expanding image text */

/* image paragraph */

#img-paragraph {
  display: none;
  vertical-align: top;
  text-align: left;
  position: absolute;
  height: 400px;
  width: 50%;
  background-color: white;
  box-shadow: 0 2.8px 2.2px rgba(0, 0, 0, 0.034), 0 6.7px 5.3px rgba(0, 0, 0, 0.048), 0 12.5px 10px rgba(0, 0, 0, 0.06), 0 22.3px 17.9px rgba(0, 0, 0, 0.072), 0 41.8px 33.4px rgba(0, 0, 0, 0.086), 0 100px 80px rgba(0, 0, 0, 0.12);
  border-radius: 7px;
  float: right;
  right: 30px;
  top: 120px;
}

#expanded-wrapper {
  width: 100%;
}

/* Closable button inside the expanded image */

.row {
  position: absolute;
  top: 80px;
}

.head1 {
  position: relative;
  left: 12px;
  top: 16px;
  color: rgb(84, 104, 217);
  font-weight: 900;
  font-size: 40px;
  font-family: 'futuralight';
  text-decoration: none;
  line-height: 1;
  padding-left:4%;
  padding-top:30px;
}

.head2 {
  position: relative;
  left: 12px;
  top: 16px;
  color: rgb(84, 104, 217);
  font-weight: 900;
  font-size: 40px;
  font-family: 'futuralight';
  text-decoration: none;
  line-height: 1;
  padding-left:4%;
  padding-top:30px;
}

.head3 {
  position: relative;
  left: 12px;
  top: 16px;
  color: rgb(84, 104, 217);
  font-weight: 900;
  font-size: 40px;
  font-family: 'futuralight';
  text-decoration: none;
  line-height: 1;
  padding-left:4%;
  padding-top:30px;
}
.head4 {
  position: relative;
  left: 12px;
  top: 16px;
  color: rgb(84, 104, 217);
  font-weight: 900;
  font-size: 40px;
  font-family: 'futuralight';
  text-decoration: none;
  line-height: 1;
  padding-left:4%;
  padding-top:30px;
}
.head5 {
  position: relative;
  left: 12px;
  top: 16px;
  color: rgb(84, 104, 217);
  font-weight: 900;
  font-size: 40px;
  font-family: 'futuralight';
  text-decoration: none;
  line-height: 1;
  padding-left:4%;
  padding-top:30px;
}
.head6 {
  position: relative;
  left: 12px;
  top: 16px;
  color: rgb(84, 104, 217);
  font-weight: 900;
  font-size: 40px;
  font-family: 'futuralight';
  text-decoration: none;
  line-height: 1;
  padding-left:4%;
  padding-top:30px;
}

.head1::before {
  content: '';
  background-color: rgb(84, 104, 217);
  width: 12px;
  height: 100%;
  position: absolute;
  right: 100%;
  bottom: -16px;
}
.head2::before {
  content: '';
  background-color: rgb(84, 104, 217);
  width: 12px;
  height: 100%;
  position: absolute;
  right: 100%;
  bottom: -16px;
}
.head3::before {
  content: '';
  background-color: rgb(84, 104, 217);
  width: 12px;
  height: 100%;
  position: absolute;
  right: 100%;
  bottom: -16px;
}
.head4::before {
  content: '';
  background-color: rgb(84, 104, 217);
  width: 12px;
  height: 100%;
  position: absolute;
  right: 100%;
  bottom: -16px;
}
.head5::before {
  content: '';
  background-color: rgb(84, 104, 217);
  width: 12px;
  height: 100%;
  position: absolute;
  right: 100%;
  bottom: -16px;
}
.head6::before {
  content: '';
  background-color: rgb(84, 104, 217);
  width: 12px;
  height: 100%;
  position: absolute;
  right: 100%;
  bottom: -16px;
}
.para1{
  width: 90%;
  position: relative;
  left: 6%;
  font-size: 17px;
  top: 60px;
  font-family: 'futuralight';
}
#column1 {
  position: absolute;
  width:250px;
  float:left;
  left:600px;
  top:30px;
  border: 0.5rem outset pink;
  outline: 0.5rem solid khaki;
}

.animate1 {
  -webkit-animation: animate1 2s normal ease-out;
  animation: animate1 2s forwards normal ease-out;
}

@-webkit-keyframes animate1 {
  0% {
      top:00px;
  }
  100% {
      position: absolute;
      top: 500px;
      left:50px;

  }
}
@keyframes animate1 {
  0% {
      top:00px;
  }
  100% {
      position: absolute;
      top: 500px;
      left:50px;
  }
}
#column2 {
  position: absolute;
  width:200px;
  float:left;
  left:300px;
  top:50px;
}

.animate2 {
  -webkit-animation: animate2 2s normal ease-out;
  animation: animate2 2s forwards normal ease-out;
}
@-webkit-keyframes animate2 {
  0% {
      top:00px;
  }
  100% {
    position: absolute;
    top: 500px;
    left:300px;
  }
}
@keyframes animate2 {
  0% {
      top:00px;
  }
  100% {
    position: absolute;
    top: 500px;
    left:300px;
  }
}
#column3 {
  position: absolute;
  width:200px;
  float:left;
  left:200px;
  top:80px;
}

.animate3 {
  -webkit-animation: animate3 2s normal ease-out;
  animation: animate3 2s forwards normal ease-out;
}
@-webkit-keyframes animate3 {
  0% {
      top:00px;
  }
  100% {
    position: absolute;
    top: 500px;
    left:500px;
  }
}
@keyframes animate3 {
  0% {
      top:00px;
  }
  100% {
    position: absolute;
    top: 500px;
    left:500px;
  }
}
#column4 {
  position: absolute;
  width:200px;
  float:left;
  left:300px;
  top:80px;
}

.animate4 {
  -webkit-animation: animate4 2s normal ease-out;
  animation: animate4 2s forwards normal ease-out;
}
@-webkit-keyframes animate4 {
  0% {
      top:00px;
  }
  100% {
    position: absolute;
    top: 500px;
    left:700px;
  }
}
@keyframes animate4 {
  0% {
      top:00px;
  }
  100% {
    position: absolute;
    top: 500px;
    left:700px;
  }
}
#column5 {
  position: absolute;
  width:200px;
  float:left;
  left:300px;
  top:80px;
  border: 0.5rem outset pink;
  outline: 0.5rem solid khaki;
}

.animate5 {
  -webkit-animation: animate5 2s normal ease-out;
  animation: animate5 2s forwards normal ease-out;
}
@-webkit-keyframes animate5 {
  0% {
    top:00px;
  }
  100% {
    position: absolute;
    top: 800px;
    left:700px;
    padding-bottom:500px;
  }
}
@keyframes animate5 {
  0% {
    top:00px;
  }
  100% {
    position: absolute;
    top: 800px;
    left:700px;
    margin-bottom:500px;
  }
}
#column6 {
  position: absolute;
  width:300px;
  float:left;
  left:600px;
  border: 0.5rem outset pink;
  outline: 0.5rem solid khaki;
  overflow:none;
}

.animate6 {
  -webkit-animation: animate6 2s normal ease-out;
  animation: animate6 2s forwards normal ease-out;
}
@-webkit-keyframes animate6 {
  0% {
      top:00px;
  }
  100% {
    position:absolute;
    top: 800px;
    left:50px;
  }
}
@keyframes animate6 {
  0% {
      top:00px;
  }
  100% {
    position:absolute;
    top: 800px;
    left:50px;
  }
}

@media only screen and (max-width: 830px) and (min-width: 760px) {
  .topnav {
    background-color: yellow;
    overflow: hidden;
  }
}

@media only screen and (max-width: 759px) and (min-width: 646px) {
  .topnav {
    background-color: red;
    overflow: hidden;
  }
}

@media only screen and (max-width: 645px) {
  .topnav {
    background-color: black;
    overflow: hidden;
  }
}

<!DOCTYPE html>

    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" type="text/css"  href="../CSS/styleprojects.css" />

    <title>Projects</title>

    Home
    Academics
    Projects
    Community Service

Body: It's because the image is an inline element and hence behaves like text. You can get rid of this effect by making the <img> tag use display: block or by setting font-size: 0 or line-height: 0 on the <div>.


来源: stackexchange

问:
Android Sqlite After Adding Column Select entries base on conditions
So this happened when I tried to mark deleted entries to have a 'deleted' value of '1' instead of deleting it.

I added a column to a database in my app using ALTER TABLE "+TABLE_NAME+" ADD COLUMN "+NEW_COLUMN_NAME+" "+type+";"); and made other appropriate changes in the database provider (when insert 0 is inserted), however, something weird happened.

After adding it, the following things happen:

SELECT * FROM TABLE_NAME - Returns all rows (as expected)

SELECT * FROM TABLE_NAME WHERE NEW_COLUMN_NAME=1 returns rows with NEW_COLUMN_NAME=1 (as expected).
However,

SELECT * FROM TABLE_NAME WHERE NEW_COLUMN_NAME=0 returns newly inserted rows (as expected).

SELECT * FROM TABLE_NAME WHERE NEW_COLUMN_NAME!=1 returns ONLY newly inserted rows (not the old rows)

SELECT * FROM TABLE_NAME WHERE NEW_COLUMN_NAME=null returns nothing.

does Android not comply with http://www.sqlite.org/lang_expr.html or did I miss something?

ran in Android 2.2 emulator.

Thanks.

答:
This one:

```<code>SELECT * FROM TABLE_NAME WHERE NEW_COLUMN_NAME = null
</code>```

Will return an empty row set in pretty much any datebase because in SQL, the expression NULL = x is false for all x (even an x of NULL). Try this instead:

```<code>SELECT * FROM TABLE_NAME WHERE NEW_COLUMN_NAME IS NULL
</code>```

Similar NULL issues will apply to this one:

```<code>SELECT * FROM TABLE_NAME WHERE NEW_COLUMN_NAME != 1
</code>```

so try:

```<code>SELECT * FROM TABLE_NAME WHERE NEW_COLUMN_NAME != 1 OR NEW_COLUMN_NAME IS NULL
</code>```

instead.

This isn't anything specific to SQLite or Android, this is just normal SQL behavior. If you don't absolutely need to allow NULL values in your columns, create them with NOT NULL (and possibly a default value) to avoid some confusion and frustration.

ContentLicense: CC BY-SA 3.0

Body:
This one:

SELECT * FROM TABLE_NAME WHERE NEW_COLUMN_NAME = null

Will return an empty row set in pretty much any datebase because in SQL, the expression NULL = x is false for all x (even an x of NULL). Try this instead:

SELECT * FROM TABLE_NAME WHERE NEW_COLUMN_NAME IS NULL

Similar NULL issues will apply to this one:

SELECT * FROM TABLE_NAME WHERE NEW_COLUMN_NAME != 1

so try:

SELECT * FROM TABLE_NAME WHERE NEW_COLUMN_NAME != 1 OR NEW_COLUMN_NAME IS NULL

instead.

This isn't anything specific to SQLite or Android, this is just normal SQL behavior. If you don't absolutely need to allow NULL values in your columns, create them with NOT NULL (and possibly a default value) to avoid some confusion and frustration.


问:
How to make the console print something by pressing a key like F2 or F3
UPDATE! I figured out how to find the keys and defined them in my code. The problem is I don't know how to make it so the console prints the selection and it gives u time to press a key. Then it gets plugged into to the switch which prints the current gun depending on the key pressed. I am also using windows 10. I also have encountered another problem I want it to print out Guns first then ask for an input (this part works fine) but then instead of just printing the attachments, it prints out both attachments and the humanized level.</p>

```<code>#include <iostream>
#include <istream>
#include <fstream>
#include <string.h>
#include <conio.h>
#include <string>

using namespace std;

#define KEY_F1 17
#define KEY_F2 18
#define KEY_F3 19
#define KEY_F4 20
#define KEY_F5 21
#define KEY_F6 22
#define KEY_F7 23
#define KEY_F8 24
#define KEY_F9 25
#define KEY_F10 26
#define KEY_F11 27
#define KEY_F12 28

#define KEY_N7 103
#define KEY_N8 104
#define KEY_N9 105

int main() {

    char gun;
    char att;
    char hum;

    char key = _getch();
    int value = key;

    cout << "" << endl;

    cout << "Developed by ! CaptaiN#9999" << endl;

    cout << "" << endl;

    cout << "Guns" << endl;

    cout << "" << endl;

    cout << "[F1]   AK" << endl;
    cout << "[F2]   MP5" << endl;
    cout << "[F3]   M2" << endl;
    cout << "[F4]   SAR" << endl;
    cout << "[F5]   Tommy" << endl;
    cout << "[F6]   Custom" << endl;
    cin >> gun;

    cout << "" << endl;

    cout << "Attachnments" << endl;

    cout << "" << endl;

    cout << "[F7]   Holosight" << endl;
    cout << "[F8]   Simplesight" << endl;
    cout << "[F9]   Silencer" << endl;
    cout << "[F10]  8x Zoom Scope" << endl;
    cout << "[F11]  16x Zoom Scope" << endl;
    cout << "[F12]  No Attachment" << endl;
    cin >> att;

    cout << "" << endl;

    cout << "Humanize Levels" << endl;

    cout << "" << endl;

    cout << "[Numpad 7]  3 (HIGH)" << endl;
    cout << "[Numpad 8]  2 (MODERATE)" << endl;
    cout << "[Numpad 9]  1 (LOW)" << endl;
    cin >> hum;

    //system("CLS");

    while (value != KEY_X) {

        switch (_getch()) {

        case KEY_F1:
            cout << "Current Gun: AK" << endl;
            break;
        case KEY_F2:
            cout << "Current Gun: MP5" << endl;
            break;
        case KEY_F3:
            cout << "Current Gun: M2" << endl;
            break;
        case KEY_F4:
            cout << "Current Gun: SAR" << endl;
            break;
        case KEY_F5:
            cout << "Current Gun: Tommy" << endl;
            break;
        case KEY_F6:
            cout << "Current Gun: Custom" << endl;
            break;
        }

        switch (att) {

        case KEY_F7:
            cout << "Current Attachment: Holosight" << endl;
            break;
        case KEY_F8:
            cout << "Current Attachment: Simplesight" << endl;
            break;
        case KEY_F9:
            cout << "Current Attachment: Silencer" << endl;
            break;
        case KEY_F10:
            cout << "Current Attachment: 8x Zoom Scope" << endl;
            break;
        case KEY_F11:
            cout << "Current Attachment: 16x Zoom Scope" << endl;
            break;
        case KEY_F12:
            cout << "Current Attachment: None" << endl;
            break;
        }

        switch (hum) {

        case KEY_N7:
            cout << "Humanized Level: 3" << endl;
            break;
        case KEY_N8:
            cout << "Humanized Level: 2" << endl;
            break;
        case KEY_N9:
            cout << "Humanized Level: 1" << endl;
            break;
        }
    }
}
</code>```

答:
there is not standard representation of function keys. So start out by working out what chars arrive at your app when Fn is pressed. Quite likely that its more than one char.

on linux you can do

```<code>cat > fn.bin
od -tx2 fn.bin
</code>```

this shows what chars are generated by Fn

ContentLicense: CC BY-SA 4.0

Body:
UPDATE! I figured out how to find the keys and defined them in my code. The problem is I don't know how to make it so the console prints the selection and it gives u time to press a key. Then it gets plugged into to the switch which prints the current gun depending on the key pressed. I am also using windows 10. I also have encountered another problem I want it to print out Guns first then ask for an input (this part works fine) but then instead of just printing the attachments, it prints out both attachments and the humanized level.

#include <iostream>
#include <istream>
#include <fstream>
#include <string.h>
#include <conio.h>
#include <string>

using namespace std;

#define KEY_F1 17
#define KEY_F2 18
#define KEY_F3 19
#define KEY_F4 20
#define KEY_F5 21
#define KEY_F6 22
#define KEY_F7 23
#define KEY_F8 24
#define KEY_F9 25
#define KEY_F10 26
#define KEY_F11 27
#define KEY_F12 28

#define KEY_N7 103
#define KEY_N8 104
#define KEY_N9 105

int main() {

    char gun;
    char att;
    char hum;

    char key = _getch();
    int value = key;

    cout << "" << endl;

    cout << "Developed by ! CaptaiN#9999" << endl;

    cout << "" << endl;

    cout << "Guns" << endl;

    cout << "" << endl;

    cout << "[F1]   AK" << endl;
    cout << "[F2]   MP5" << endl;
    cout << "[F3]   M2" << endl;
    cout << "[F4]   SAR" << endl;
    cout << "[F5]   Tommy" << endl;
    cout << "[F6]   Custom" << endl;
    cin >> gun;

    cout << "" << endl;

    cout << "Attachnments" << endl;

    cout << "" << endl;

    cout << "[F7]   Holosight" << endl;
    cout << "[F8]   Simplesight" << endl;
    cout << "[F9]   Silencer" << endl;
    cout << "[F10]  8x Zoom Scope" << endl;
    cout << "[F11]  16x Zoom Scope" << endl;
    cout << "[F12]  No Attachment" << endl;
    cin >> att;

    cout << "" << endl;

    cout << "Humanize Levels" << endl;

    cout << "" << endl;

    cout << "[Numpad 7]  3 (HIGH)" << endl;
    cout << "[Numpad 8]  2 (MODERATE)" << endl;
    cout << "[Numpad 9]  1 (LOW)" << endl;
    cin >> hum;

    //system("CLS");

    while (value != KEY_X) {

        switch (_getch()) {

        case KEY_F1:
            cout << "Current Gun: AK" << endl;
            break;
        case KEY_F2:
            cout << "Current Gun: MP5" << endl;
            break;
        case KEY_F3:
            cout << "Current Gun: M2" << endl;
            break;
        case KEY_F4:
            cout << "Current Gun: SAR" << endl;
            break;
        case KEY_F5:
            cout << "Current Gun: Tommy" << endl;
            break;
        case KEY_F6:
            cout << "Current Gun: Custom" << endl;
            break;
        }

        switch (att) {

        case KEY_F7:
            cout << "Current Attachment: Holosight" << endl;
            break;
        case KEY_F8:
            cout << "Current Attachment: Simplesight" << endl;
            break;
        case KEY_F9:
            cout << "Current Attachment: Silencer" << endl;
            break;
        case KEY_F10:
            cout << "Current Attachment: 8x Zoom Scope" << endl;
            break;
        case KEY_F11:
            cout << "Current Attachment: 16x Zoom Scope" << endl;
            break;
        case KEY_F12:
            cout << "Current Attachment: None" << endl;
            break;
        }

        switch (hum) {

        case KEY_N7:
            cout << "Humanized Level: 3" << endl;
            break;
        case KEY_N8:
            cout << "Humanized Level: 2" << endl;
            break;
        case KEY_N9:
            cout << "Humanized Level: 1" << endl;
            break;
        }
    }
}

Body:
there is not standard representation of function keys. So start out by working out what chars arrive at your app when Fn is pressed. Quite likely that its more than one char.

on linux you can do

cat > fn.bin
od -tx2 fn.bin

this shows what chars are generated by Fn


问:
Change scroll axis on mobile devices (touch)
I have a container that can be scrolled through horizontally. This was done by rotating the container by 90 degrees.
This is however only a visual workaround: the visual horizontal scrolling is done by physical vertical scrolling. On mobile devices this is very counter-intuitive.

Is there any way to manipulate the scrolling behaviour so that the container can be scrolled through with horizontal touch gestures?

Here is a simplified demonstration of the container:

.item {
  background: black;
  height: 50px;
  width: 50px;
  margin: 5px;
}

.container {
  background: yellow;
  width: fit-content;
  height: 300px;
  overflow-y: scroll;
  transform: rotate(-90deg);
  transform-origin: top right;
}```
<pre class="snippet-code-html lang-html prettyprint-override"><code><div class="container">

  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>

</div></code>```

答:
Instead of using transform, actualy place the elements side by side in a flex container.

Because you don't want the elements to shrink with the container size you a can set a min-width on the items:

.item {
  background: black;
  height: 50px;
  width: 50px;
  margin: 5px;
  min-width:50px;
}

.container {
  display:flex;
  background: yellow;
  width: 300px;
  overflow-x: scroll;
}```
<pre class="snippet-code-html lang-html prettyprint-override"><code><div class="container">

  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>

</div></code>```

Body:
Instead of using transform, actualy place the elements side by side in a flex container.

Because you don't want the elements to shrink with the container size you a can set a min-width on the items:

.item {
  background: black;
  height: 50px;
  width: 50px;
  margin: 5px;
  min-width:50px;
}

.container {
  display:flex;
  background: yellow;
  width: 300px;
  overflow-x: scroll;
}

<div class="container">

  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>

</div>


问:
Why does flutter return an error for Firestore methods inside of classes but is fine inside of widget?
So I tried creating a model classes similar to rails, laravel or other frameworks so that I could organize my code better and I wanted to add instance methods to save data to firebase here is my class. However, for some reason when I call the save method on my event class. I get this error MissingPluginException(No implementation found for method DocumentReference#setData on channel plugins.flutter.io/cloud_firestore).

I tried running flutter clean, after googling, upgrading flutter, uninstalling the app, and running packages get and nothing worked. Finally I tried just creating normal function inside of my widget component to create a new document and add data. The function worked fine without an error. Also, yes, I did the appropriate imports of importing cloud firestore into my event class as well geoflutterfire. Why am I getting the error and is there a way to organize my code? Do firestore methods not work in dart files that aren't widgets that inherit from stateless widget or statfefull widget? I tried importing foundation and material dart packages and they were both greyed out with Firestore and my privateEvent class obviously not using it.

```<code>  final bool feedbackLocationOrActivity;
  final String id;
  final bool feedbackTimeAndDate;
  final String name;
  final String mediaUrl;
  final String address;
  final DateTime startTime;
  final DateTime endTime;
  List categories;
  final String creatorId;
  final String groupId;
  final GeoFirePoint location;
  List coHosts;
  final String details;
  final bool guestsCanInviteFriends;

  PrivateEvent(
      {this.feedbackLocationOrActivity,
      this.id,
      this.feedbackTimeAndDate,
      this.name,
      this.mediaUrl,
      this.address,
      this.startTime,
      this.endTime,
      this.categories,
      this.creatorId,
      this.location,
      this.coHosts,
      this.guestsCanInviteFriends,
      this.details,
      this.groupId});

  factory PrivateEvent.fromDocument(DocumentSnapshot doc) {
    return PrivateEvent(
        id: doc['id'],
        feedbackLocationOrActivity: doc['feedbackLocationOrActivity'],
        feedbackTimeAndDate: doc['feedbackTimeAndDate'],
        name: doc['name'],
        mediaUrl: doc['mediaUrl'],
        address: doc['address'],
        startTime: doc['startTime'],
        endTime: doc['endTime'],
        categories: doc['categories'],
        creatorId: doc['creatorId'],
        groupId: doc['groupId'],
        coHosts: doc['coHosts'],
        guestsCanInviteFriends: doc['guestsCanInviteFriends'],
        details: doc['details'],
        location: doc['location']);
  }

  save() async {
    return Firestore.instance
        .collection('privateEvents')
        .document(this.groupId)
        .collection("events")
        .add({
      "id": this.id,
      "feedbackLocationOrActivity": this.feedbackLocationOrActivity,
      "feedbackTimeAndDate": this.feedbackTimeAndDate,
      "name": this.name,
      "mediaUrl": this.mediaUrl,
      "address": this.address,
      "startTime": this.startTime,
      "endTime": this.endTime,
      "categories": FieldValue.arrayUnion(this.categories),
      "creatorId": this.creatorId,
      "location": this.location.data,
      "details": this.details,
      "coHosts": FieldValue.arrayUnion(this.coHosts),
      "guestsCanInviteFriends": this.guestsCanInviteFriends
    }).then((response) {
      response.updateData({"id": response.documentID});
      return true;
    }).catchError((onError) {
      print("this is the error $onError");
      return false;
    });
  }
}

The save method is the method that should save it to the database however it gets an error.

Here is where I call it.

createEvent({screenWidth, screenHeight, isLandscape}) async {
    setState(() {
      loading = true;
    });
    final String mediaUrl = await uploadImage(file);
    if (mediaUrl.isEmpty || mediaUrl == null) {
      setState(() {
        loading = false;
      });
      eventTimeWarning(
          screenWidth: screenWidth,
          screenHeight: screenHeight,
          isLandscape: isLandscape,
          warningMessage:
              "Your image didn't upload properly. There could be a problem with your internet connection. Please try again");
      return;
    }
    PrivateEvent privateEvent = PrivateEvent(
        feedbackTimeAndDate: feedbackTimeAndDate,
        feedbackLocationOrActivity: feedbackLocationOrActivity,
        name: eventName,
        mediaUrl: mediaUrl,
        address: eventAddress,
        startTime: eventStartTimeAndDate,
        endTime: eventEndTimeAndDate,
        categories: selectedCategories(),
        creatorId: Provider.of<UserData>(context).getUserId,
        location: eventLocation,
        guestsCanInviteFriends: guestsCanInviteFriends,
        details: detailsController.text.trim(),
        groupId:
            Provider.of<PrivateGroupNormalData>(context).getGroupId);

    final bool eventUploadSuccess = await sendEventInfo();
    if (!eventUploadSuccess) {
      setState(() {
        eventTimeWarning(
            screenWidth: screenWidth,
            screenHeight: screenHeight,
            isLandscape: isLandscape,
            warningMessage:
                "There was a problem creating your event. Please, check your internet connection and try again.");
        loading = false;
      });
      return;
    }
    print("EVENT CREATED SUCCESSFULLY!");
  }

As I said before. The above doesn't work. However On creating a function within the widget. The data is added to the database and there is no missingexception error.

Here is the working version.

Future<bool> sendEventInfo({String mediaUrl}) {
    return Firestore.instance
        .collection('privateEvents')
        .document(Provider.of<PrivateGroupNormalData>(context).getGroupId)
        .collection("events")
        .add({
      "feedbackLocationOrActivity": this.feedbackLocationOrActivity,
      "feedbackTimeAndDate": this.feedbackTimeAndDate,
      "name": this.eventName,
      "mediaUrl": mediaUrl,
      "address": eventAddress,
      "startTime": eventStartTimeAndDate,
      "endTime": eventEndTimeAndDate,
      "categories": selectedCategories(),
      "creatorId": Provider.of<UserData>(context).getUserId,
      "location": eventLocation.data,
      "details": detailsController.text.trim(),
      "coHosts": FieldValue.arrayUnion(),
      "guestsCanInviteFriends": this.guestsCanInviteFriends
    }).then((response) {
      response.updateData({"id": response.documentID});
      return true;
    }).catchError((onError) {
      print("this is the error $onError");
      return false;
    });
  }

All I do is replace the call to instance method with the call to the above function and now it works fine without the missing plugin error.
</code>```

答: The answer is that I had to make my Firestore Instance a static instance to be able to access it properly.</p>

Body:
So I tried creating a model classes similar to rails, laravel or other frameworks so that I could organize my code better and I wanted to add instance methods to save data to firebase here is my class. However, for some reason when I call the save method on my event class. I get this error MissingPluginException(No implementation found for method DocumentReference#setData on channel plugins.flutter.io/cloud_firestore).

I tried running flutter clean, after googling, upgrading flutter, uninstalling the app, and running packages get and nothing worked. Finally I tried just creating normal function inside of my widget component to create a new document and add data. The function worked fine without an error. Also, yes, I did the appropriate imports of importing cloud firestore into my event class as well geoflutterfire. Why am I getting the error and is there a way to organize my code? Do firestore methods not work in dart files that aren't widgets that inherit from stateless widget or statfefull widget? I tried importing foundation and material dart packages and they were both greyed out with Firestore and my privateEvent class obviously not using it.

  final bool feedbackLocationOrActivity;
  final String id;
  final bool feedbackTimeAndDate;
  final String name;
  final String mediaUrl;
  final String address;
  final DateTime startTime;
  final DateTime endTime;
  List categories;
  final String creatorId;
  final String groupId;
  final GeoFirePoint location;
  List coHosts;
  final String details;
  final bool guestsCanInviteFriends;

  PrivateEvent(
      {this.feedbackLocationOrActivity,
      this.id,
      this.feedbackTimeAndDate,
      this.name,
      this.mediaUrl,
      this.address,
      this.startTime,
      this.endTime,
      this.categories,
      this.creatorId,
      this.location,
      this.coHosts,
      this.guestsCanInviteFriends,
      this.details,
      this.groupId});

  factory PrivateEvent.fromDocument(DocumentSnapshot doc) {
    return PrivateEvent(
        id: doc['id'],
        feedbackLocationOrActivity: doc['feedbackLocationOrActivity'],
        feedbackTimeAndDate: doc['feedbackTimeAndDate'],
        name: doc['name'],
        mediaUrl: doc['mediaUrl'],
        address: doc['address'],
        startTime: doc['startTime'],
        endTime: doc['endTime'],
        categories: doc['categories'],
        creatorId: doc['creatorId'],
        groupId: doc['groupId'],
        coHosts: doc['coHosts'],
        guestsCanInviteFriends: doc['guestsCanInviteFriends'],
        details: doc['details'],
        location: doc['location']);
  }

  save() async {
    return Firestore.instance
        .collection('privateEvents')
        .document(this.groupId)
        .collection("events")
        .add({
      "id": this.id,
      "feedbackLocationOrActivity": this.feedbackLocationOrActivity,
      "feedbackTimeAndDate": this.feedbackTimeAndDate,
      "name": this.name,
      "mediaUrl": this.mediaUrl,
      "address": this.address,
      "startTime": this.startTime,
      "endTime": this.endTime,
      "categories": FieldValue.arrayUnion(this.categories),
      "creatorId": this.creatorId,
      "location": this.location.data,
      "details": this.details,
      "coHosts": FieldValue.arrayUnion(this.coHosts),
      "guestsCanInviteFriends": this.guestsCanInviteFriends
    }).then((response) {
      response.updateData({"id": response.documentID});
      return true;
    }).catchError((onError) {
      print("this is the error $onError");
      return false;
    });
  }
}

The save method is the method that should save it to the database however it gets an error.

Here is where I call it.

createEvent({screenWidth, screenHeight, isLandscape}) async {
    setState(() {
      loading = true;
    });
    final String mediaUrl = await uploadImage(file);
    if (mediaUrl.isEmpty || mediaUrl == null) {
      setState(() {
        loading = false;
      });
      eventTimeWarning(
          screenWidth: screenWidth,
          screenHeight: screenHeight,
          isLandscape: isLandscape,
          warningMessage:
              "Your image didn't upload properly. There could be a problem with your internet connection. Please try again");
      return;
    }
    PrivateEvent privateEvent = PrivateEvent(
        feedbackTimeAndDate: feedbackTimeAndDate,
        feedbackLocationOrActivity: feedbackLocationOrActivity,
        name: eventName,
        mediaUrl: mediaUrl,
        address: eventAddress,
        startTime: eventStartTimeAndDate,
        endTime: eventEndTimeAndDate,
        categories: selectedCategories(),
        creatorId: Provider.of<UserData>(context).getUserId,
        location: eventLocation,
        guestsCanInviteFriends: guestsCanInviteFriends,
        details: detailsController.text.trim(),
        groupId:
            Provider.of<PrivateGroupNormalData>(context).getGroupId);

    final bool eventUploadSuccess = await sendEventInfo();
    if (!eventUploadSuccess) {
      setState(() {
        eventTimeWarning(
            screenWidth: screenWidth,
            screenHeight: screenHeight,
            isLandscape: isLandscape,
            warningMessage:
                "There was a problem creating your event. Please, check your internet connection and try again.");
        loading = false;
      });
      return;
    }
    print("EVENT CREATED SUCCESSFULLY!");
  }

As I said before. The above doesn't work. However On creating a function within the widget. The data is added to the database and there is no missingexception error.

Here is the working version.

Future<bool> sendEventInfo({String mediaUrl}) {
    return Firestore.instance
        .collection('privateEvents')
        .document(Provider.of<PrivateGroupNormalData>(context).getGroupId)
        .collection("events")
        .add({
      "feedbackLocationOrActivity": this.feedbackLocationOrActivity,
      "feedbackTimeAndDate": this.feedbackTimeAndDate,
      "name": this.eventName,
      "mediaUrl": mediaUrl,
      "address": eventAddress,
      "startTime": eventStartTimeAndDate,
      "endTime": eventEndTimeAndDate,
      "categories": selectedCategories(),
      "creatorId": Provider.of<UserData>(context).getUserId,
      "location": eventLocation.data,
      "details": detailsController.text.trim(),
      "coHosts": FieldValue.arrayUnion(),
      "guestsCanInviteFriends": this.guestsCanInviteFriends
    }).then((response) {
      response.updateData({"id": response.documentID});
      return true;
    }).catchError((onError) {
      print("this is the error $onError");
      return false;
    });
  }

All I do is replace the call to instance method with the call to the above function and now it works fine without the missing plugin error.


问:
How do I undo "replace"?
I didn't realize that "replace" meant the log messages from the previous file will be gone, now the log messages start with when I replaced the file and so on.

I need a way to revert it back to the previous file (before I replaced it). Is there a way to do that?

答:
In essence, you've deleted the old file, so the advice on Resurrecting Deleted Items will link the log trail back to where it was before your replace.

You could then apply the differences between the old and new files in-place, instead of either deleting the old file and adding a new one or copying another file on top, however you "replace"d the file the first time, to preserve history.

Of course, whether the discontinuity in the log is a problem is really a matter of judgment.  You could simply note in the log for a new revision which old revision in which to find the previous file of that name.

Title: How do I undo "replace"?


问:
Parse error when text is split on multi lines: "control characters from U+0000 through U+001F must be escaped"
I'm getting a "parse error" when I split a text line on multiple lines and show the JSON file on screen with the command jq . words.json.

The JSON file with the text value on a single line looks like this

```<code>{
    "words" : "one two three four five"
}
</code>```

The command jq . words.json works fine and shows the JSON file on screen.

But when I split the value "one two three four five" on two lines and run the same command I get a parse error

```<code>{
    "words" : "one two
    three four five"
                   ^
}

</code>```

parse error: Invalid string: control characters from U+0000 through
U+001F must be escaped at line 3, column 20

The parse error points to the " character at the end of the third line.

How can I solve this?

答:
The parse error points to the " at the end of the third line.

The way jq flags this error may be counterintuitive, but the error in the JSON precedes the indicated quote-mark.

If the error is non-obvious, it may be that an end-quote is missing on the prior key or value.  In this case, the value that matches the criteria U+0000 through U+001F could be U+000A, which is the line feed character in ASCII.

In the case of this question, the line feed was inserted intentionally.  But, unescaped, this is invalid JSON.

Body:
I'm getting a "parse error" when I split a text line on multiple lines and show the JSON file on screen with the command jq . words.json.

The JSON file with the text value on a single line looks like this

{
    "words" : "one two three four five"
}

The command jq . words.json works fine and shows the JSON file on screen.

But when I split the value "one two three four five" on two lines and run the same command I get a parse error

{
    "words" : "one two
    three four five"
                   ^
}

parse error: Invalid string: control characters from U+0000 through
U+001F must be escaped at line 3, column 20

The parse error points to the " character at the end of the third line.

How can I solve this?


问:
set wallpaper to the device without crop or zoom in
When I set an image from my app to be as background for the device, the device zoom in the image and crop it, but I don't want that, I want to set the image as the same size for it.

here is a short video explaining what I mean "just 15 sec" the short video

hint: the first one is my app, second is Zedge app, the same photo.
so I want my app to like edge app when set image as wallpaper

Here is my code

```<code>item_home_image = findViewById(R.id.item_home_image);
item_home_image.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
    if (checkPermission()) {
        final Intent intent = getIntent();
        String url = intent.getStringExtra("imageUrl");
        Picasso.with(PicassoDisplayImageAdapter.this).load(url).into(new Target() {
            @RequiresApi(api = Build.VERSION_CODES.N)
            @Override
            public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
                WallpaperManager wallpaperManager = WallpaperManager.getInstance(PicassoDisplayImageAdapter.this);
                try {
                    wallpaperManager.setBitmap(bitmap);
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
                Toasty.normal(PicassoDisplayImageAdapter.this, "تم تغيير الخلفية بنجاح", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onBitmapFailed(final Drawable errorDrawable) {
                Toasty.error(PicassoDisplayImageAdapter.this, "فشل تحميل الصورة", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onPrepareLoad(final Drawable placeHolderDrawable) {
                Toasty.normal(PicassoDisplayImageAdapter.this, "جاري التحميل", Toast.LENGTH_SHORT).show();
            }
        });
    }
 }
});
</code>```

image when set it from my app

image when set it from Zedge app

答:
```<code> public void getBitmapFromURL(String path) {

        Glide.with(WaalDetail.this)
                .asBitmap()
                .load(path)
                .into(new SimpleTarget<Bitmap>() {
                    @Override
                    public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
                        try {
                            WallpaperManager.getInstance(getApplicationContext()).setBitmap(resource);
                            Toast.makeText(WaalDetail.this, "Set wallpaper successfully!", Toast.LENGTH_LONG).show();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }

                    }
                });
    }
</code>```

this is works for me perfectly.

Body:
When I set an image from my app to be as background for the device, the device zoom in the image and crop it, but I don't want that, I want to set the image as the same size for it.

here is a short video explaining what I mean "just 15 sec" the short video

hint: the first one is my app, second is Zedge app, the same photo.
so I want my app to like edge app when set image as wallpaper

Here is my code

item_home_image = findViewById(R.id.item_home_image);
item_home_image.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
    if (checkPermission()) {
        final Intent intent = getIntent();
        String url = intent.getStringExtra("imageUrl");
        Picasso.with(PicassoDisplayImageAdapter.this).load(url).into(new Target() {
            @RequiresApi(api = Build.VERSION_CODES.N)
            @Override
            public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
                WallpaperManager wallpaperManager = WallpaperManager.getInstance(PicassoDisplayImageAdapter.this);
                try {
                    wallpaperManager.setBitmap(bitmap);
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
                Toasty.normal(PicassoDisplayImageAdapter.this, "تم تغيير الخلفية بنجاح", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onBitmapFailed(final Drawable errorDrawable) {
                Toasty.error(PicassoDisplayImageAdapter.this, "فشل تحميل الصورة", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onPrepareLoad(final Drawable placeHolderDrawable) {
                Toasty.normal(PicassoDisplayImageAdapter.this, "جاري التحميل", Toast.LENGTH_SHORT).show();
            }
        });
    }
 }
});

image when set it from my app

image when set it from Zedge app

Body:
 public void getBitmapFromURL(String path) {

        Glide.with(WaalDetail.this)
                .asBitmap()
                .load(path)
                .into(new SimpleTarget<Bitmap>() {
                    @Override
                    public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
                        try {
                            WallpaperManager.getInstance(getApplicationContext()).setBitmap(resource);
                            Toast.makeText(WaalDetail.this, "Set wallpaper successfully!", Toast.LENGTH_LONG).show();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }

                    }
                });
    }

this is works for me perfectly.


问:
How to find argmax of last 2 axes
Hey I have seen this question - Numpy: argmax over multiple axes without loop but the output is not the shape I desire. So for example, if I give the function an array of dimension: 10x20x12x12x2x2, it will output an array of dimension: 10x20x12x12, which values are the indices</p>

答:
Make a simpler, but I think still relevant array:

```<code>In [268]: arr = np.random.randint(0,20,(4,1,3,2))
In [269]: arr
Out[269]:
array([[[[16,  1],
         [13, 17],
         [19,  0]]],

       [[[ 2, 13],
         [12,  9],
         [ 6,  6]]],

       [[[13,  2],
         [18, 10],
         [ 7, 10]]],

       [[[ 8, 19],
         [ 6, 17],
         [ 2,  6]]]])
</code>```

reshape as suggested in the link:

```<code>In [270]: arr1 = arr.reshape(arr.shape[:-2]+(-1,))
In [271]: arr1
Out[271]:
array([[[16,  1, 13, 17, 19,  0]],

       [[ 2, 13, 12,  9,  6,  6]],

       [[13,  2, 18, 10,  7, 10]],

       [[ 8, 19,  6, 17,  2,  6]]])
</code>```

then we can take the max and argmax on the last dimension:

```<code>In [272]: np.max(arr1, -1)
Out[272]:
array([[19],
       [13],
       [18],
       [19]])
In [273]: idx = np.argmax(arr1, -1)
In [274]: idx
Out[274]:
array([[4],
       [1],
       [2],
       [1]])
</code>```

we can recover the max from the argmax with indexing work:

```<code>In [282]: ij = np.ix_(np.arange(4),np.arange(1))
In [283]: ij+(idx,)
Out[283]:
(array([[0],
        [1],
        [2],
        [3]]),
 array([[0]]),
 array([[4],
        [1],
        [2],
        [1]]))
In [284]: arr1[ij+(idx,)]
Out[284]:
array([[19],
       [13],
       [18],
       [19]])
</code>```

With unravel we can apply this to arr:

```<code>In [285]: idx1 = np.unravel_index(idx, (3,2))
In [286]: idx1
Out[286]:
(array([[2],
        [0],
        [1],
        [0]]),
 array([[0],
        [1],
        [0],
        [1]]))
In [287]: arr[ij+idx1]       # tuple concatenate
Out[287]:
array([[19],
       [13],
       [18],
       [19]])
</code>```

So the max on the last 2 axes of arr is still the shape of the first 2.

So even though arr is (4,1,3,2), the useful argmax does not have this shape.  Instead we need a tuple of 4 arrays, one for each dimension of arr.  Advanced indexing like this on more than 2 dimensions is tricky, and hard to visualize.  I had to play around with this quite a while.

With your dimensions:

```<code>In [322]: barr = np.random.randint(0,100,(10,20,12,12,2,2))
In [323]: barr1 = barr.reshape(barr.shape[:-2]+(-1,))
In [324]: ms = np.max(barr1, axis=-1)
In [325]: idx = np.argmax(barr1,-1)
In [326]: idx1 = np.unravel_index(idx, barr.shape[-2:])
In [327]: ij = np.ix_(*[np.arange(i) for i in barr.shape[:-2]])
In [328]: np.allclose(barr[ij+idx1], ms)
Out[328]: True
</code>```

edit

We could just as well simplify this task to working with a 2d array:

```<code>In [65]: barr2 = barr.reshape(-1,4)
In [66]: idx2 = np.argmax(barr2, axis=1)
In [67]: idx2.shape
Out[67]: (28800,)
In [68]: np.allclose(idx.ravel(), idx2)
Out[68]: True
In [69]: ms2 = barr2[np.arange(barr2.shape[0]),idx2]
In [70]: ms2.shape
Out[70]: (28800,)
In [72]: np.allclose(ms2.reshape(barr.shape[:-2]), ms)
Out[72]: True
</code>```

column_stack is wrong with the multidimensional idx1, joining on axis 1.  We want to join on a new trailing axis, with stack:

```<code>In [77]: np.column_stack(idx1).shape
Out[77]: (10, 40, 12, 12)
In [78]: np.stack(idx1,axis=-1).shape
Out[78]: (10, 20, 12, 12, 2)
In [79]: np.allclose(x, np.stack(idx1,-1).reshape(-1,2))
Out[79]: True
</code>```

But I don't see the value of such a stack.  The linked question does ask for such an array, but doesn't show how such an array might be used.

Title: How to find argmax of last 2 axes

Body:
Make a simpler, but I think still relevant array:

In [268]: arr = np.random.randint(0,20,(4,1,3,2))
In [269]: arr
Out[269]:
array([[[[16,  1],
         [13, 17],
         [19,  0]]],

       [[[ 2, 13],
         [12,  9],
         [ 6,  6]]],

       [[[13,  2],
         [18, 10],
         [ 7, 10]]],

       [[[ 8, 19],
         [ 6, 17],
         [ 2,  6]]]])

reshape as suggested in the link:

In [270]: arr1 = arr.reshape(arr.shape[:-2]+(-1,))
In [271]: arr1
Out[271]:
array([[[16,  1, 13, 17, 19,  0]],

       [[ 2, 13, 12,  9,  6,  6]],

       [[13,  2, 18, 10,  7, 10]],

       [[ 8, 19,  6, 17,  2,  6]]])

then we can take the max and argmax on the last dimension:

In [272]: np.max(arr1, -1)
Out[272]:
array([[19],
       [13],
       [18],
       [19]])
In [273]: idx = np.argmax(arr1, -1)
In [274]: idx
Out[274]:
array([[4],
       [1],
       [2],
       [1]])

we can recover the max from the argmax with indexing work:

In [282]: ij = np.ix_(np.arange(4),np.arange(1))
In [283]: ij+(idx,)
Out[283]:
(array([[0],
        [1],
        [2],
        [3]]),
 array([[0]]),
 array([[4],
        [1],
        [2],
        [1]]))
In [284]: arr1[ij+(idx,)]
Out[284]:
array([[19],
       [13],
       [18],
       [19]])

With unravel we can apply this to arr:

In [285]: idx1 = np.unravel_index(idx, (3,2))
In [286]: idx1
Out[286]:
(array([[2],
        [0],
        [1],
        [0]]),
 array([[0],
        [1],
        [0],
        [1]]))
In [287]: arr[ij+idx1]       # tuple concatenate
Out[287]:
array([[19],
       [13],
       [18],
       [19]])

So the max on the last 2 axes of arr is still the shape of the first 2.

So even though arr is (4,1,3,2), the useful argmax does not have this shape.  Instead we need a tuple of 4 arrays, one for each dimension of arr.  Advanced indexing like this on more than 2 dimensions is tricky, and hard to visualize.  I had to play around with this quite a while.

With your dimensions:

In [322]: barr = np.random.randint(0,100,(10,20,12,12,2,2))
In [323]: barr1 = barr.reshape(barr.shape[:-2]+(-1,))
In [324]: ms = np.max(barr1, axis=-1)
In [325]: idx = np.argmax(barr1,-1)
In [326]: idx1 = np.unravel_index(idx, barr.shape[-2:])
In [327]: ij = np.ix_(*[np.arange(i) for i in barr.shape[:-2]])
In [328]: np.allclose(barr[ij+idx1], ms)
Out[328]: True

edit

We could just as well simplify this task to working with a 2d array:

In [65]: barr2 = barr.reshape(-1,4)
In [66]: idx2 = np.argmax(barr2, axis=1)
In [67]: idx2.shape
Out[67]: (28800,)
In [68]: np.allclose(idx.ravel(), idx2)
Out[68]: True
In [69]: ms2 = barr2[np.arange(barr2.shape[0]),idx2]
In [70]: ms2.shape
Out[70]: (28800,)
In [72]: np.allclose(ms2.reshape(barr.shape[:-2]), ms)
Out[72]: True

column_stack is wrong with the multidimensional idx1, joining on axis 1.  We want to join on a new trailing axis, with stack:

In [77]: np.column_stack(idx1).shape
Out[77]: (10, 40, 12, 12)
In [78]: np.stack(idx1,axis=-1).shape
Out[78]: (10, 20, 12, 12, 2)
In [79]: np.allclose(x, np.stack(idx1,-1).reshape(-1,2))
Out[79]: True

But I don't see the value of such a stack.  The linked question does ask for such an array, but doesn't show how such an array might be used.


问:
Creating a dictionary from two lists? While taking an average of values?
Wizards of stackoverflow,

I wish to combine two lists to create a dictionary, I have used dict & zip, however it does not meet what I require.

If had these lists

```<code>  keys = ['a', 'a', 'b', 'c']
values = [6, 2, 3, 4]
</code>```

I would like for the dictionary to reflect the average value such that the output would be:

```<code>a_dict = {'a' : 4, 'b' : 3, 'c' : 4}
</code>```

as a bonus but not required, if this is possible is there anyway to get a count of each duplicate?
i.e. output would be followed by 'a' was counted twice, other than just doing the count in the keys.

答:
calculating avg and frequency of each key  dic = {key: [avg, frequency]}

```<code>keys = ['a', 'a', 'b', 'c']
values = [6, 2, 3, 4]

dic = {i:[[], 0] for i in keys}

for k, v in zip(keys, values):
    dic[k][0].append(v)
    dic[k][1]+=1

for k, v in dic.items():
    dic[k][0] = sum(dic[k][0])/len(dic[k][0])

print(dic)
</code>```

output

```<code>{'a': [4.0, 2], 'b': [3.0, 1], 'c': [4.0, 1]}
</code>```

Body:
Wizards of stackoverflow,

I wish to combine two lists to create a dictionary, I have used dict & zip, however it does not meet what I require.

If had these lists

  keys = ['a', 'a', 'b', 'c']
values = [6, 2, 3, 4]

I would like for the dictionary to reflect the average value such that the output would be:

a_dict = {'a' : 4, 'b' : 3, 'c' : 4}

as a bonus but not required, if this is possible is there anyway to get a count of each duplicate?
i.e. output would be followed by 'a' was counted twice, other than just doing the count in the keys.

Body:
calculating avg and frequency of each key  dic = {key: [avg, frequency]}

keys = ['a', 'a', 'b', 'c']
values = [6, 2, 3, 4]

dic = {i:[[], 0] for i in keys}

for k, v in zip(keys, values):
    dic[k][0].append(v)
    dic[k][1]+=1

for k, v in dic.items():
    dic[k][0] = sum(dic[k][0])/len(dic[k][0])

print(dic)

output

{'a': [4.0, 2], 'b': [3.0, 1], 'c': [4.0, 1]}


问:
Is this a correct application of recursion? (displaying items of a stack)
```<code>#include <stdio.h>
#include <stdlib.h>

struct node{
    int value;
    struct node *nextPtr;
};

typedef struct node Node;

void display(Node *head);
void push(Node **top, int newvalue);

int main(){

    Node *topPtr = NULL;

    push (&topPtr, 123);     // test with 123

    display(topPtr);

}

void display(Node *head){
    if (head == NULL){
        printf("\n");
        return;
    } else {
        printf("\n%d", head->value);    //
        display(head->nextPtr);         // is this recursion?
    }
}

void push(Node **top, int newvalue){
    Node *newlinkPtr = calloc(1,sizeof(Node));

    if(newlinkPtr){
        newlinkPtr->value = newvalue;
        newlinkPtr->nextPtr = *top;
        *top = newlinkPtr;
    } else {
        printf("\nNo memory.\n");
    }
}
</code>```

Is the display() function a correct recursion application? I have this doubt because usually I do the recursive call inside the printf, but not this time. Is it still a recursion? If it isn't is there a way to do everything inside the printf?

答:
There's no such thing as a 'correct application of recursion'. As long as you're getting the result you want with reasonably use of computation and memory resources, any implementation should be fine.

For the specific case above, yes it looks like you've implemented recursion correctly and it will give you a result with reasonable time complexity.

Body:
#include <stdio.h>
#include <stdlib.h>

struct node{
    int value;
    struct node *nextPtr;
};

typedef struct node Node;

void display(Node *head);
void push(Node **top, int newvalue);

int main(){

    Node *topPtr = NULL;

    push (&topPtr, 123);     // test with 123

    display(topPtr);

}

void display(Node *head){
    if (head == NULL){
        printf("\n");
        return;
    } else {
        printf("\n%d", head->value);    //
        display(head->nextPtr);         // is this recursion?
    }
}

void push(Node **top, int newvalue){
    Node *newlinkPtr = calloc(1,sizeof(Node));

    if(newlinkPtr){
        newlinkPtr->value = newvalue;
        newlinkPtr->nextPtr = *top;
        *top = newlinkPtr;
    } else {
        printf("\nNo memory.\n");
    }
}

Is the display() function a correct recursion application? I have this doubt because usually I do the recursive call inside the printf, but not this time. Is it still a recursion? If it isn't is there a way to do everything inside the printf?


问:
Dataframe column not converting to date after groupby
I am reading a dataset in which there are few columns. In the one column is of date. Date contains mixed format for date (both 01 and 1) and year(both 2020 and 20).

I wanted to group data based on date and merge the content of other columns so I used this:

```<code>covid_df['Date'] = pd.to_datetime(covid_df['Date'],format="%d/%m/%y").dt.strftime("%d/%m/%y")
covid_df=covid_df.groupby('Date').agg(lambda col: col.tolist()).reset_index()
</code>```

Now, that I have what I wanted I checked the columns data type again and found that now date column is again having object data type which means a string. So I converted my data frame one more time and sort it based on date column and do a tail operation. But sort is not happening correctly:

```<code>covid_df['Date'] = pd.to_datetime(covid_df['Date'],format="%d/%m/%y").dt.strftime("%d/%m/%y")
covid_df.sort_values(by='Date')
print(covid_df.tail(10))
</code>```

Output:

```<code>'
'
'
118  30/04/20  ...  [33, 1403, 1, 42, 403, 56, 38, 3439, 7, 4082, ...
119  30/05/20  ...  [33, 3436, 3, 1024, 3376, 289, 415, 2, 17386, ...
120  31/01/20  ...                                                [1]
121  31/03/20  ...  [40, 10, 15, 13, 8, 97, 5, 73, 40, 3, 54, 83, ...

[10 rows x 5 columns]

</code>```

You can clearly see the date is not in sorted order.

答:
As suggested by Trenton,

pd.to_datetime(covid_df['Date'],format="%d/%m/%y").dt.strftime("%d/%m/%y") converts it to a datetime and then back to a string

Body:
I am reading a dataset in which there are few columns. In the one column is of date. Date contains mixed format for date (both 01 and 1) and year(both 2020 and 20).

I wanted to group data based on date and merge the content of other columns so I used this:

covid_df['Date'] = pd.to_datetime(covid_df['Date'],format="%d/%m/%y").dt.strftime("%d/%m/%y")
covid_df=covid_df.groupby('Date').agg(lambda col: col.tolist()).reset_index()

Now, that I have what I wanted I checked the columns data type again and found that now date column is again having object data type which means a string. So I converted my data frame one more time and sort it based on date column and do a tail operation. But sort is not happening correctly:

covid_df['Date'] = pd.to_datetime(covid_df['Date'],format="%d/%m/%y").dt.strftime("%d/%m/%y")
covid_df.sort_values(by='Date')
print(covid_df.tail(10))

Output:

'
'
'
118  30/04/20  ...  [33, 1403, 1, 42, 403, 56, 38, 3439, 7, 4082, ...
119  30/05/20  ...  [33, 3436, 3, 1024, 3376, 289, 415, 2, 17386, ...
120  31/01/20  ...                                                [1]
121  31/03/20  ...  [40, 10, 15, 13, 8, 97, 5, 73, 40, 3, 54, 83, ...

[10 rows x 5 columns]

You can clearly see the date is not in sorted order.


问:
AWS Step Functions TaskTimedOut
I am using boto3 in my activity workers and I came upon a TaskTimedOut when calling the SendTaskFailure:

```<code>botocore.errorfactory.TaskTimedOut: An error occurred (TaskTimedOut) when calling the SendTaskFailure operation: Task Timed Out: 'arn:aws:states:eu-west-2:statemachinearn:activityname'
</code>```

I think this happens because the connection pool gets full sometimes which makes the request not being fulfilled (even though a new connection is created).

I know it is possible to set a timeout value for Tasks and Parallel States but that does not have anything to do with calling the send_task_failure/send_task_success methods.

Does anyone have any idea on how to solve this?

答:
I can explain one scenario which I encountered in step function.
I was using nested state machines and in my main state machine, I used to get exception like 'timeout when invoking state machine', one in 1000s. As it was transient error, i had to handle it as per specs provided by AWS so I explicitly added retry for framework exceptions like below.</p>

```<code>"Retry": [
    {
      "ErrorEquals": [
        "StepFunctions.SdkClientException"
      ],
      "IntervalSeconds": 10,
      "MaxAttempts": 4,
      "BackoffRate": 2
    }
  ]
</code>```

Title: AWS Step Functions TaskTimedOut

Body:
I am using boto3 in my activity workers and I came upon a TaskTimedOut when calling the SendTaskFailure:

botocore.errorfactory.TaskTimedOut: An error occurred (TaskTimedOut) when calling the SendTaskFailure operation: Task Timed Out: 'arn:aws:states:eu-west-2:statemachinearn:activityname'

I think this happens because the connection pool gets full sometimes which makes the request not being fulfilled (even though a new connection is created).

I know it is possible to set a timeout value for Tasks and Parallel States but that does not have anything to do with calling the send_task_failure/send_task_success methods.

Does anyone have any idea on how to solve this?

Body:
I can explain one scenario which I encountered in step function.
I was using nested state machines and in my main state machine, I used to get exception like 'timeout when invoking state machine', one in 1000s. As it was transient error, i had to handle it as per specs provided by AWS so I explicitly added retry for framework exceptions like below.

"Retry": [
    {
      "ErrorEquals": [
        "StepFunctions.SdkClientException"
      ],
      "IntervalSeconds": 10,
      "MaxAttempts": 4,
      "BackoffRate": 2
    }
  ]


问:
How to substitute the 0 and nan values of a pandas pivot table with the row average?
I used this to substitute the nan values with the row average for my pivot table

```<code>pivot = pivot.apply(lambda row: row.fillna(row.mean()), axis=1)
</code>```

However, how can I include the row values that are 0 in the transformation (transform both nan and 0 with the row average)?

I tried to apply a lambda function before executing the command above to transform the 0 values in nan, but it did not work. Below what I tried to convert 0s to nan :

```<code>pivot = pivot.apply(lambda x == np.nan if x == 0 else x )
</code>```

答:
There are syntax issues with your lambda function.

Firstly you need to declare the input variable of the lambda.

Secondly when you assign something use = instead of ==.

Edit - You can't make assignments within a lambda so just writing np.nan should do.

Can you try this instead.

```<code>pivot = pivot.apply(lambda x: np.nan if x == 0 else x )

</code>```

Body:
I used this to substitute the nan values with the row average for my pivot table

pivot = pivot.apply(lambda row: row.fillna(row.mean()), axis=1)

However, how can I include the row values that are 0 in the transformation (transform both nan and 0 with the row average)?

I tried to apply a lambda function before executing the command above to transform the 0 values in nan, but it did not work. Below what I tried to convert 0s to nan :

pivot = pivot.apply(lambda x == np.nan if x == 0 else x )

Body:
There are syntax issues with your lambda function.

Firstly you need to declare the input variable of the lambda.

Secondly when you assign something use = instead of ==.

Edit - You can't make assignments within a lambda so just writing np.nan should do.

Can you try this instead.

pivot = pivot.apply(lambda x: np.nan if x == 0 else x )


答:
```<code>keys = ['a', 'a', 'b', 'c']
values = [6, 2, 3, 4]
d, count_dict=dict(), dict()
for i in range(len(keys)):
    try:
        d[keys[i]]+=values[i]
        count_dict[keys[i]]+=1
    except KeyError:
        d[keys[i]]=values[i]
        count_dict[keys[i]]=1
for keys,values in d.items():
    d[keys]=d[keys]/count_dict[keys]
    print(f'{keys} comes {count_dict[keys]} times')
print(d)
</code>```

Title: Creating a dictionary from two lists? While taking an average of values?


问:
How to resolve memory related errors that arise from interaction between C objects in a C++ wrapper?

The problem

I am writing a thin C++ wrapper around an object oriented C library. The idea was to automate memory management, but so far its not been very automatic. Basically when I use my wrapper classes, I get all kinds of memory access and inappropriate freeing problems.

Minimal example of C library

Lets say the C library consists of A and B classes, each of which have a few 'methods' associated with them:

```<code>#include <memory>
#include "cstring"
#include "iostream"

extern "C" {
typedef struct {
    unsigned char *string;
} A;

A *c_newA(const char *string) {
    A *a = (A *) malloc(sizeof(A)); // yes I know, don't use malloc in C++. This is a demo to simulate the C library that uses it.
    auto *s = (char *) malloc(strlen(string) + 1);
    strcpy(s, string);
    a->string = (unsigned char *) s;
    return a;
}

void c_freeA(A *a) {
    free(a->string);
    free(a);
}

void c_printA(A *a) {
    std::cout << a->string << std::endl;
}

typedef struct {
    A *firstA;
    A *secondA;
} B;

B *c_newB(const char *first, const char *second) {
    B *b = (B *) malloc(sizeof(B));
    b->firstA = c_newA(first);
    b->secondA = c_newA(second);
    return b;
}

void c_freeB(B *b) {
    c_freeA(b->firstA);
    c_freeA(b->secondA);
    free(b);
}

void c_printB(B *b) {
    std::cout << b->firstA->string << ", " << b->secondA->string << std::endl;
}

A *c_getFirstA(B *b) {
    return b->firstA;
}

A *c_getSecondA(B *b) {
    return b->secondA;
}

}
</code>```

Test the 'C lib'

```<code>void testA() {
    A *a = c_newA("An A");
    c_printA(a);
    c_freeA(a);
    // outputs: "An A"
    // valgrind is happy =]
}
</code>```
```<code>void testB() {
    B *b = c_newB("first A", "second A");
    c_printB(b);
    c_freeB(b);
    // outputs: "first A, second A"
    // valgrind is happy =]
}

</code>```

Wrapper classes for A and B

```<code>class AWrapper {

    struct deleter {
        void operator()(A *a) {
            c_freeA(a);
        }
    };

    std::unique_ptr<A, deleter> aptr_;
public:

    explicit AWrapper(A *a)
            : aptr_(a) {
    }

    static AWrapper fromString(const std::string &string) { // preferred way of instantiating
        A *a = c_newA(string.c_str());
        return AWrapper(a);
    }

    void printA() {
        c_printA(aptr_.get());
    }
};

class BWrapper {

    struct deleter {
        void operator()(B *b) {
            c_freeB(b);
        }
    };

    std::unique_ptr<B, deleter> bptr_;
public:
    explicit BWrapper(B *b)
            : bptr_(std::unique_ptr<B, deleter>(b)) {
    }

    static BWrapper fromString(const std::string &first, const std::string &second) {
        B *b = c_newB(first.c_str(), second.c_str());
        return BWrapper(b);
    }

    void printB() {
        c_printB(bptr_.get());
    }

    AWrapper getFirstA(){
        return AWrapper(c_getFirstA(bptr_.get()));
    }

    AWrapper getSecondA(){
        return AWrapper(c_getSecondA(bptr_.get()));
    }

};
</code>```

Wrapper tests

```<code>
void testAWrapper() {
    AWrapper a = AWrapper::fromString("An A");
    a.printA();
    // outputs "An A"
    // valgrind is happy =]
}

void testBWrapper() {
    BWrapper b = BWrapper::fromString("first A", "second A");
    b.printB();
    // outputs "first A"
    // valgrind is happy =]
}

</code>```

Demonstration of the problem

Great, so I move on and develop the full wrapper (lot of classes) and realise that when classes like this (i.e. aggregation relationship) are both in scope, C++ will automatically call the descructors of both classes separately, but because of the structure of the underlying library (i.e. the calls to free), we get memory problems:

```<code>void testUsingAWrapperAndBWrapperTogether() {
    BWrapper b = BWrapper::fromString("first A", "second A");
    AWrapper a1 = b.getFirstA();
    // valgrind no happy =[

}

</code>```

Valgrind output

Things I've tried

Cloning not possible

The first thing I tried was to take a copy of A, rather than having them try to free the same A. This, while a good idea, is not possible in my case because of the nature of the library I'm using. There is actually a catching mechanism in place so that when you create a new A with a string its seen before, it'll give you back the same A. See this question for my attempts at cloning A.

Custom destructors

I took the code for the C library destructors (freeA and freeB here) and copied them into my source code. Then I tried to modify them such that A does not get freed by B. This has partially worked. Some instances of memory problems have been resolved, but because this idea does not tackle the problem at hand (just kind of temporarily glosses over the main issue), new problems keep popping up, some of which are obscure and difficult to debug.

The question

So at last we arive at the question: How can I modify this C++ wrapper to resolve the memory problems that arise due to the interactions between the underlying C objects? Can I make better use of smart pointers? Should I abandon the C wrapper completly and just use the libraries pointers as is? Or is there a better way I haven't thought of?

Thanks in advance.

Edits: response to the comments

Since asking the previous question (linked above) I have restructed my code so that the wrapper is being developed and built in the same library as the one it wraps. So the objects are no longer opaque.

The pointers are generated from function calls to the library, which uses calloc or malloc to allocate.

In the real code A is raptor_uri* (typdef librdf_uri*) from raptor2 and is allocated with librdf_new_uri while B is raptor_term* (aka librdf_node*) and allocated with librdf_new_node_* functions. The librdf_node has a librdf_uri field.

Edit 2

I can also point to the line of code where the same A is returned if its the same string. See line 137 here

答:
You are freeing A twice

```<code>BWrapper b = BWrapper::fromString("first A", "second A");
</code>```

When b goes out of scope, c_freeB is called which also calls c_freeA

```<code>AWrapper a1 = b.getFirstA();
</code>```

Wraps A with another unique_ptr, then when a1 goes out of scope it will call c_freeA on the same A.

Note that getFirstA in BWrapper gives ownership of an A to another unique_ptr when using the AWrapper constructor.

Ways to fix this:

Don't let B manage A memory, but since you are using a lib that won't be possible.

Let BWrapper manage A, don't let AWrapper manage A and make sure the BWrapper exists when using AWrapper. That is, use a raw pointer in AWrapper instead of a smart pointer.

Make a copy of A in the AWrapper(A *) constructor, for this you might want to use a function from the library.

Edit:

shared_ptr won't work in this case because c_freeB will call c_freeA anyways.

Edit 2:

In this specific case considering the raptor lib you mentioned, you could try the following:

```<code>explicit AWrapper(A *a)
            : aptr_(raptor_uri_copy(a)) {
}
</code>```

assuming that A is a raptor_uri. raptor_uri_copy(raptor_uri *) will increase the reference count and return the same passed pointer. Then, even if raptor_free_uri is called twice on the same raptor_uri * it will call free only when the counter becomes zero.

Body:
The problem

I am writing a thin C++ wrapper around an object oriented C library. The idea was to automate memory management, but so far its not been very automatic. Basically when I use my wrapper classes, I get all kinds of memory access and inappropriate freeing problems.

Minimal example of C library

Lets say the C library consists of A and B classes, each of which have a few 'methods' associated with them:

#include <memory>
#include "cstring"
#include "iostream"

extern "C" {
typedef struct {
    unsigned char *string;
} A;

A *c_newA(const char *string) {
    A *a = (A *) malloc(sizeof(A)); // yes I know, don't use malloc in C++. This is a demo to simulate the C library that uses it.
    auto *s = (char *) malloc(strlen(string) + 1);
    strcpy(s, string);
    a->string = (unsigned char *) s;
    return a;
}

void c_freeA(A *a) {
    free(a->string);
    free(a);
}

void c_printA(A *a) {
    std::cout <string << std::endl;
}

typedef struct {
    A *firstA;
    A *secondA;
} B;

B *c_newB(const char *first, const char *second) {
    B *b = (B *) malloc(sizeof(B));
    b->firstA = c_newA(first);
    b->secondA = c_newA(second);
    return b;
}

void c_freeB(B *b) {
    c_freeA(b->firstA);
    c_freeA(b->secondA);
    free(b);
}

void c_printB(B *b) {
    std::cout <firstA->string << ", " <secondA->string << std::endl;
}

A *c_getFirstA(B *b) {
    return b->firstA;
}

A *c_getSecondA(B *b) {
    return b->secondA;
}

}

Test the 'C lib'

void testA() {
    A *a = c_newA("An A");
    c_printA(a);
    c_freeA(a);
    // outputs: "An A"
    // valgrind is happy =]
}

void testB() {
    B *b = c_newB("first A", "second A");
    c_printB(b);
    c_freeB(b);
    // outputs: "first A, second A"
    // valgrind is happy =]
}

Wrapper classes for A and B

class AWrapper {

    struct deleter {
        void operator()(A *a) {
            c_freeA(a);
        }
    };

    std::unique_ptr aptr_;
public:

    explicit AWrapper(A *a)
            : aptr_(a) {
    }

    static AWrapper fromString(const std::string &string) { // preferred way of instantiating
        A *a = c_newA(string.c_str());
        return AWrapper(a);
    }

    void printA() {
        c_printA(aptr_.get());
    }
};

class BWrapper {

    struct deleter {
        void operator()(B *b) {
            c_freeB(b);
        }
    };

    std::unique_ptr bptr_;
public:
    explicit BWrapper(B *b)
            : bptr_(std::unique_ptr(b)) {
    }

    static BWrapper fromString(const std::string &first, const std::string &second) {
        B *b = c_newB(first.c_str(), second.c_str());
        return BWrapper(b);
    }

    void printB() {
        c_printB(bptr_.get());
    }

    AWrapper getFirstA(){
        return AWrapper(c_getFirstA(bptr_.get()));
    }

    AWrapper getSecondA(){
        return AWrapper(c_getSecondA(bptr_.get()));
    }

};

Wrapper tests

void testAWrapper() {
    AWrapper a = AWrapper::fromString("An A");
    a.printA();
    // outputs "An A"
    // valgrind is happy =]
}

void testBWrapper() {
    BWrapper b = BWrapper::fromString("first A", "second A");
    b.printB();
    // outputs "first A"
    // valgrind is happy =]
}

Demonstration of the problem

Great, so I move on and develop the full wrapper (lot of classes) and realise that when classes like this (i.e. aggregation relationship) are both in scope, C++ will automatically call the descructors of both classes separately, but because of the structure of the underlying library (i.e. the calls to free), we get memory problems:

void testUsingAWrapperAndBWrapperTogether() {
    BWrapper b = BWrapper::fromString("first A", "second A");
    AWrapper a1 = b.getFirstA();
    // valgrind no happy =[

}

Valgrind output

Things I've tried

Cloning not possible

The first thing I tried was to take a copy of A, rather than having them try to free the same A. This, while a good idea, is not possible in my case because of the nature of the library I'm using. There is actually a catching mechanism in place so that when you create a new A with a string its seen before, it'll give you back the same A. See this question for my attempts at cloning A.

Custom destructors

I took the code for the C library destructors (freeA and freeB here) and copied them into my source code. Then I tried to modify them such that A does not get freed by B. This has partially worked. Some instances of memory problems have been resolved, but because this idea does not tackle the problem at hand (just kind of temporarily glosses over the main issue), new problems keep popping up, some of which are obscure and difficult to debug.

The question

So at last we arive at the question: How can I modify this C++ wrapper to resolve the memory problems that arise due to the interactions between the underlying C objects? Can I make better use of smart pointers? Should I abandon the C wrapper completly and just use the libraries pointers as is? Or is there a better way I haven't thought of?

Thanks in advance.

Edits: response to the comments

Since asking the previous question (linked above) I have restructed my code so that the wrapper is being developed and built in the same library as the one it wraps. So the objects are no longer opaque.

The pointers are generated from function calls to the library, which uses calloc or malloc to allocate.

In the real code A is raptor_uri* (typdef librdf_uri*) from raptor2 and is allocated with librdf_new_uri while B is raptor_term* (aka librdf_node*) and allocated with librdf_new_node_* functions. The librdf_node has a librdf_uri field.

Edit 2

I can also point to the line of code where the same A is returned if its the same string. See line 137 here

Body:
You are freeing A twice

BWrapper b = BWrapper::fromString("first A", "second A");

When b goes out of scope, c_freeB is called which also calls c_freeA

AWrapper a1 = b.getFirstA();

Wraps A with another unique_ptr, then when a1 goes out of scope it will call c_freeA on the same A.

Note that getFirstA in BWrapper gives ownership of an A to another unique_ptr when using the AWrapper constructor.

Ways to fix this:

Don't let B manage A memory, but since you are using a lib that won't be possible.

Let BWrapper manage A, don't let AWrapper manage A and make sure the BWrapper exists when using AWrapper. That is, use a raw pointer in AWrapper instead of a smart pointer.

Make a copy of A in the AWrapper(A *) constructor, for this you might want to use a function from the library.

Edit:

shared_ptr won't work in this case because c_freeB will call c_freeA anyways.

Edit 2:

In this specific case considering the raptor lib you mentioned, you could try the following:

explicit AWrapper(A *a)
            : aptr_(raptor_uri_copy(a)) {
}

assuming that A is a raptor_uri. raptor_uri_copy(raptor_uri *) will increase the reference count and return the same passed pointer. Then, even if raptor_free_uri is called twice on the same raptor_uri * it will call free only when the counter becomes zero.


问:
Use mapreduce to read CSVs (where not all columns match) and combine into DataFrame
I'm using Julia 1.4.2.

I want to use mapreduce() to:

Read a bunch of CSVs, then

Combine them into one big DataFrame.

First the preliminaries:

```<code>using CSV, DataFrames

# Create CSVs
df1 = DataFrame([['a', 'b', 'c'], [1, 2, 3]],
                ["name", "id"])
df2 = DataFrame([['d', 'e', 'f'], [4, 5, 6]],
                ["name", "id"])
# NOTE: This df has an extra column not present in the other two
df3 = DataFrame([['x', 'y', 'z'], [7, 8, 9], [11, 22, 33]],
                ["name", "id", "num"])
CSV.write("df1.csv", df1)
CSV.write("df2.csv", df2)
CSV.write("df3.csv", df3)

# Get Vector of file paths for the above-created CSVs.
# Regex because there might be other files in working directory.
files = filter(x -> occursin(r"df\d\.csv$", x),
               readdir(join=true))
</code>```

If I call map() and reduce() separately, I get what I want:

```<code># Import the above-created CSVs as a Vector of DataFrames
dfs = map(x -> CSV.File(x) |> DataFrame,
          files)

# Combine them into one big DataFrame
df = reduce(vcat, dfs, cols=:union)
</code>```

(NOTE: df3 has an extra column not present in the other two, so I need the cols=:union argument.)

However, I want to condense the above map() and reduce() calls into a mapreduce() call. Here's what I've tried:

```<code>df = mapreduce(x -> CSV.File(x) |> DataFrame,
               x -> vcat(x, cols=:union),
               files)
# MethodError: no method matching (::var"#16#18")(::DataFrame, ::DataFrame)

df = mapreduce(x -> CSV.File(x) |> DataFrame,
               vcat,
               files,
               cols=:union)
# MethodError: no method matching _mapreduce_dim(::var"#21#22", ::typeof(vcat), ::NamedTuple{(:cols,),Tuple{Symbol}}, ::Array{String,1}, ::Colon)
</code>```

The root of my problem is that I don't understand the documentation for mapreduce(). How can I pass named arguments to the binary function (the op argument)? E.g., I can add the cols=:union argument to reduce(op, itr), as in reduce(vcat, dfs, cols=:union). How can I pass arguments to the binary function op in mapreduce(f, op, itrs...)?

答:
op must be a two-argument function since it combines the current state with the newly mapped element. Try this:

```<code>df = mapreduce(x -> CSV.File(x) |> DataFrame,
               (x, y) -> vcat(x, y; cols=:union),
               files)
</code>```

Body:
I'm using Julia 1.4.2.

I want to use mapreduce() to:

Read a bunch of CSVs, then

Combine them into one big DataFrame.

First the preliminaries:

using CSV, DataFrames

# Create CSVs
df1 = DataFrame([['a', 'b', 'c'], [1, 2, 3]],
                ["name", "id"])
df2 = DataFrame([['d', 'e', 'f'], [4, 5, 6]],
                ["name", "id"])
# NOTE: This df has an extra column not present in the other two
df3 = DataFrame([['x', 'y', 'z'], [7, 8, 9], [11, 22, 33]],
                ["name", "id", "num"])
CSV.write("df1.csv", df1)
CSV.write("df2.csv", df2)
CSV.write("df3.csv", df3)

# Get Vector of file paths for the above-created CSVs.
# Regex because there might be other files in working directory.
files = filter(x -> occursin(r"df\d\.csv$", x),
               readdir(join=true))

If I call map() and reduce() separately, I get what I want:

# Import the above-created CSVs as a Vector of DataFrames
dfs = map(x -> CSV.File(x) |> DataFrame,
          files)

# Combine them into one big DataFrame
df = reduce(vcat, dfs, cols=:union)

(NOTE: df3 has an extra column not present in the other two, so I need the cols=:union argument.)

However, I want to condense the above map() and reduce() calls into a mapreduce() call. Here's what I've tried:

df = mapreduce(x -> CSV.File(x) |> DataFrame,
               x -> vcat(x, cols=:union),
               files)
# MethodError: no method matching (::var"#16#18")(::DataFrame, ::DataFrame)

df = mapreduce(x -> CSV.File(x) |> DataFrame,
               vcat,
               files,
               cols=:union)
# MethodError: no method matching _mapreduce_dim(::var"#21#22", ::typeof(vcat), ::NamedTuple{(:cols,),Tuple{Symbol}}, ::Array{String,1}, ::Colon)

The root of my problem is that I don't understand the documentation for mapreduce(). How can I pass named arguments to the binary function (the op argument)? E.g., I can add the cols=:union argument to reduce(op, itr), as in reduce(vcat, dfs, cols=:union). How can I pass arguments to the binary function op in mapreduce(f, op, itrs...)?

Body:
op must be a two-argument function since it combines the current state with the newly mapped element. Try this:

df = mapreduce(x -> CSV.File(x) |> DataFrame,
               (x, y) -> vcat(x, y; cols=:union),
               files)


问:
Sorting columns having lists with reference to each other in pandas
Suppose my data frame is like:

```<code>   A             B           Date
[1,3,2]    ['a','b','c']     date1
</code>```

I want to sort both the columns but with reference to each other. Like the output should be:

```<code>   A             B           Date
[1,2,3]    ['a','c','b']     date1
</code>```

Now if these had been two lists only I would have sorted through zip method.

But as these are columns of data frame. I am not sure how to use apply method to sort these with reference to each other.

My dataframe as a whole is sorted on the basis of third column (date). Now for each such dates the other two columns have list, each having same number of values. I want to sort those lists on the basis of each other

答:
Similar to cs95's solution, but with sort_values and sort_index:

```<code># sample data
df = pd.DataFrame({
    'A':[[1,3,2],[2,1]],
    'B':[['a','b','c'],['c','d']],
    'Date':['date1','date2']
})

df[['A','B']] = (df[['A','B']].apply(pd.Series.explode)
    .sort_values('A',kind='mergesort')
    .sort_index(kind='merge_sort')
    .groupby(level=0).agg(list)
)
</code>```

Output:

```<code>           A          B   Date
0  [1, 2, 3]  [a, c, b]  date1
1     [1, 2]     [d, c]  date2
</code>```

Body:
Suppose my data frame is like:

   A             B           Date
[1,3,2]    ['a','b','c']     date1

I want to sort both the columns but with reference to each other. Like the output should be:

   A             B           Date
[1,2,3]    ['a','c','b']     date1

Now if these had been two lists only I would have sorted through zip method.

But as these are columns of data frame. I am not sure how to use apply method to sort these with reference to each other.

My dataframe as a whole is sorted on the basis of third column (date). Now for each such dates the other two columns have list, each having same number of values. I want to sort those lists on the basis of each other

Body:
Similar to cs95's solution, but with sort_values and sort_index:

# sample data
df = pd.DataFrame({
    'A':[[1,3,2],[2,1]],
    'B':[['a','b','c'],['c','d']],
    'Date':['date1','date2']
})

df[['A','B']] = (df[['A','B']].apply(pd.Series.explode)
    .sort_values('A',kind='mergesort')
    .sort_index(kind='merge_sort')
    .groupby(level=0).agg(list)
)

Output:

           A          B   Date
0  [1, 2, 3]  [a, c, b]  date1
1     [1, 2]     [d, c]  date2