Cuando uso la función setDailyAssessmentInfo
, aparece el error:
Error de estimación de gas con el siguiente mensaje (ver más abajo). Es probable que la ejecución de la transacción falle. ¿Quieres forzar el envío? Excepción de máquina virtual al procesar la transacción: código de operación no válido
Aquí está mi código:
pragma solidity ^0.4.21;
contract DailyAssessmentScoreContract {
struct dailyAssessment{
string dailyAssessmentId;
string[] period;
uint[] score;
}
dailyAssessment[] daily_assessment;
function stringsEqual(string storage _a, string memory _b) internal returns (bool) {
bytes storage a = bytes(_a);
bytes memory b = bytes(_b);
if (a.length != b.length)
return false;
// @todo unroll this loop
for (uint i = 0; i < a.length; i ++)
if (a[i] != b[i])
return false;
return true;
}
function stringToUint(string s) constant returns (uint result) {
bytes memory b = bytes(s);
uint i;
result = 0;
for (i = 0; i < b.length; i++) {
uint c = uint(b[i]);
if (c >= 48 && c <= 57) {
result = result * 10 + (c - 48);
}
}
}
function setDailyAssessmentInfo(string _dailyAssessmentId, string _period, string _score) public {
bool write = false;
uint score = stringToUint(_score);
for(uint i=0; i<=daily_assessment.length; i++)
{
if(stringsEqual(daily_assessment[i].dailyAssessmentId, _dailyAssessmentId))
{
daily_assessment[i].period.push(_period);
daily_assessment[i].score.push(score);
write = true;
}
}
if(write==false)
{
daily_assessment[i].dailyAssessmentId=_dailyAssessmentId;
daily_assessment[i].period.push(_period);
daily_assessment[i].score.push(score);
}
}
function getDailyAssessmentInfo(string _dailyAssessmentId) public constant returns (uint) {
uint score;
for(uint i=0;i<=daily_assessment.length;i++)
{
if(stringsEqual(daily_assessment[i].dailyAssessmentId, _dailyAssessmentId))
{
uint sum = 0;
uint scoreLength = daily_assessment[i].score.length;
for(uint j=0;j<=scoreLength;j++)
{
sum = sum + daily_assessment[i].score[j];
}
score = sum / scoreLength;
}
}
return (score);
}
}
El problema radica en
for(uint i=0; i<=daily_assessment.length; i++)
Al iterar sobre la matriz, si crece demasiado, podría causar un error de falta de gas y, dado que es una matriz de longitud variable, está causando un error de estimación de gas.
Puede cambiar su diseño para usar mapping
en lugar de matriz.
mapping(string => dailyAssessment) daily_assessment;
Utilice un map
en el que key
será el daily assessment id
y value
será la estructura dailyAssessment
.
function setDailyAssessmentInfo(string _dailyAssessmentId, string _period, string _score) public {
bool write = false;
uint score = stringToUint(_score);
dailyAssessment storage assessment = daily_assesment[_dailyAssesmentId];
if(assesment.dailyAssesmentId == _dailyAssesmentId)
{
assessment.period.push(_period);
assessment.score.push(score);
write = true;
}
Con respecto a su comentario: "aquí hay otro problema que quiero usar" getDailyAssessmentInfo "para obtener la suma de la matriz de puntuación, un aumento de error me gusta por encima de la estimación de gas con error con el siguiente mensaje", el problema es exactamente el mismo. Parece que está calculando el promedio de las puntuaciones en esta getDailyAssessmentInfo
función. Se trata de utilizar un bucle sobre toda la puntuación y calcular el promedio. Entonces, la solución ideal sería calcular el promedio sin usar bucles.
Le sugiero que calcule el promedio al insertar los datos (en setDailyAssessmentInfo
), guárdelo y simplemente obtenga ese puntaje promedio usando una función de obtención. Pero recuerde que el cálculo no debe usar loop. He usado una idea simple en el siguiente código para hacerlo.
struct dailyAssessment{
string dailyAssessmentId;
string[] period;
uint[] score;
uint averageScore;
}
function getDailyAssessmentInfo(string _id) returns (uint){
return daily_assessment[_id].averageScore;
}
function setDailyAssessmentInfo(string _dailyAssessmentId, string _period, uint _score) public {
uint average = daily_assessment[_dailyAssessmentId].averageScore;
uint N = daily_assessment[_dailyAssessmentId].score.length;
uint newAverage = (average * N + _score) / (N + 1);
daily_assessment[_dailyAssessmentId].averageScore = newAverage;
Espero haber ayudado.
Kyrie
Kyrie
biplavo